The Samba-Bugzilla – Attachment 860 Details for
Bug 2176
[kernel oops] browsing a directory
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
cifs-unicode-to-mbcs-conversion-bof-fix
linux-2.6.10-rc3-bk14-cifs-unicode-to-mbcs-conversion-bof-fix.patch (text/plain), 15.54 KB, created by
Han, Donghoon
on 2004-12-22 03:22:53 UTC
(
hide
)
Description:
cifs-unicode-to-mbcs-conversion-bof-fix
Filename:
MIME Type:
Creator:
Han, Donghoon
Created:
2004-12-22 03:22:53 UTC
Size:
15.54 KB
patch
obsolete
>--- linux-2.6.10-rc3-bk14-original/fs/cifs/cifs_unicode.h 2004-10-19 06:55:28.000000000 +0900 >+++ linux-2.6.10-rc3-bk14/fs/cifs/cifs_unicode.h 2004-12-22 16:45:40.000000000 +0900 >@@ -29,6 +29,8 @@ > * The upper/lower functions are based on a table created by mkupr. > * This is a compressed table of upper and lower case conversion. > * >+ * Modified By: Han, Donghoon (nazgul33 at nazgul33 dot com) 2004/12/21 >+ * > */ > > #include <asm/byteorder.h> >@@ -61,6 +63,7 @@ extern struct UniCaseRange UniLowerRange > #ifdef __KERNEL__ > int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *); > int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *); >+int cifs_strfromUCS_le_fitBufLen(char *, int, const wchar_t *, int, const struct nls_table *); > #endif > > /* >--- linux-2.6.10-rc3-bk14-original/fs/cifs/cifs_unicode.c 2004-10-19 06:55:36.000000000 +0900 >+++ linux-2.6.10-rc3-bk14/fs/cifs/cifs_unicode.c 2004-12-22 16:45:40.000000000 +0900 >@@ -17,6 +17,8 @@ > * You should have received a copy of the GNU General Public License > * along with this program; if not, write to the Free Software > * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ * >+ * Modified By: Han, Donghoon (nazgul33 at nazgul33 dot com) 2004/12/21 > */ > #include <linux/fs.h> > #include "cifs_unicode.h" >@@ -50,6 +52,7 @@ cifs_strfromUCS_le(char *to, const wchar > } > } > to[outlen] = 0; >+ > return outlen; > } > >@@ -85,3 +88,53 @@ cifs_strtoUCS(wchar_t * to, const char * > return i; > } > >+/* >+ * NAME: cifs_strfromUCS() >+ * >+ * FUNCTION: Convert little-endian unicode string to character string >+ * Converted multibyte string never exceeds to buffer length >+ * if exceeds, remainder will be represented as '~' >+ */ >+int cifs_strfromUCS_le_fitBufLen( char * to, int to_len, const wchar_t * from, int from_len, const struct nls_table *codepage ) >+{ >+ int i,j; >+ int outlen = 0; >+ >+ to_len--; // reserved for null termination >+ >+ for ( i=0; (i<from_len) && from[i]; i++ ) { >+ int charlen; >+ char conv_buffer[NLS_MAX_CHARSET_SIZE]; >+ >+ charlen = >+ codepage->uni2char(le16_to_cpu(from[i]), conv_buffer, >+ NLS_MAX_CHARSET_SIZE); >+ if ( charlen > 0 ) { >+ /* test if converted mbChar fits in to buffer */ >+ if ( ( charlen < to_len - outlen ) || >+ ((charlen == to_len - outlen) >+ && ((i+1>=from_len) || from[i+1]==0)) ) { >+ for(j=0; j<charlen; j++) to[outlen+j]=conv_buffer[j]; >+ outlen += charlen; >+ } else { >+ to[outlen++]='~'; >+ break; // no more room to convert >+ } >+ } else { >+ /* test if we ran out of buffer */ >+ if ( (outlen+1<to_len) || >+ ((outlen+1==to_len) && >+ ((i+1>=from_len) || from[i+1]==0)) ) { >+ to[outlen++]='?'; >+ } else { >+ to[outlen++]='~'; >+ break; >+ } >+ } >+ } >+ to[outlen] = 0; >+ >+ return outlen; >+} >+ >+ >--- linux-2.6.10-rc3-bk14-original/fs/cifs/file.c 2004-12-22 18:59:11.661706592 +0900 >+++ linux-2.6.10-rc3-bk14/fs/cifs/file.c 2004-12-22 16:45:40.000000000 +0900 >@@ -19,6 +19,9 @@ > * You should have received a copy of the GNU Lesser General Public License > * along with this library; if not, write to the Free Software > * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ * >+ * >+ * Modified By: Han, Donghoon (nazgul33 at nazgul33 dot com) 2004/12/21 > */ > #include <linux/fs.h> > #include <linux/stat.h> >@@ -37,8 +40,7 @@ > > extern int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir); /* BB removeme BB */ > >-int >-cifs_open(struct inode *inode, struct file *file) >+int cifs_open(struct inode *inode, struct file *file) > { > int rc = -EACCES; > int xid, oplock; >@@ -1800,7 +1802,8 @@ construct_dentry(struct qstr *qstring, s > > static void reset_resume_key(struct file * dir_file, > unsigned char * filename, >- unsigned int len,int Unicode,struct nls_table * nls_tab) { >+ unsigned int len) >+{ > struct cifsFileInfo *cifsFile; > > cifsFile = (struct cifsFileInfo *)dir_file->private_data; >@@ -1810,24 +1813,24 @@ static void reset_resume_key(struct file > kfree(cifsFile->search_resume_name); > } > >- if(Unicode) >- len *= 2; >+ /* for safe null termination */ > cifsFile->resume_name_length = len; > > cifsFile->search_resume_name = >- kmalloc(cifsFile->resume_name_length, GFP_KERNEL); >+ kmalloc(cifsFile->resume_name_length + 2, GFP_KERNEL); > > if(cifsFile->search_resume_name == NULL) { > cERROR(1,("failed new resume key allocate, length %d", > cifsFile->resume_name_length)); > return; > } >- if(Unicode) >- cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name, >- filename, len, nls_tab); >- else >- memcpy(cifsFile->search_resume_name, filename, >- cifsFile->resume_name_length); >+ >+ memcpy(cifsFile->search_resume_name, filename, >+ cifsFile->resume_name_length); >+ >+ /* for safe null termination */ >+ cifsFile->search_resume_name[len] = 0; >+ cifsFile->search_resume_name[len+1] = 0; > cFYI(1,("Reset resume key to: %s with len %d",filename,len)); > return; > } >@@ -1836,13 +1839,16 @@ static void reset_resume_key(struct file > > static int > cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData, >- struct file *file, filldir_t filldir, void *direntry) >+ struct file *file, filldir_t filldir, void *direntry, char * mbFileName ) > { > struct inode *tmp_inode; > struct dentry *tmp_dentry; > int object_type,rc; > >- pqstring->name = pfindData->FileName; >+ if ( mbFileName == NULL ) >+ mbFileName = pfindData->FileName; >+ >+ pqstring->name = mbFileName; > /* pqstring->len is already set by caller */ > > rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); >@@ -1858,12 +1864,12 @@ cifs_filldir(struct qstr *pqstring, FILE > /* new inode created, let us hash it */ > insert_inode_hash(tmp_inode); > } /* else if inode number changed do we rehash it? */ >- rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos, >+ rc = filldir(direntry, mbFileName, pqstring->len, file->f_pos, > tmp_inode->i_ino, object_type); > if(rc) { > /* due to readdir error we need to recalculate resume > key so next readdir will restart on right entry */ >- cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName)); >+ cFYI(1,("Error %d on filldir of %s",rc ,mbFileName)); > } > dput(tmp_dentry); > return rc; >@@ -1872,14 +1878,17 @@ cifs_filldir(struct qstr *pqstring, FILE > static int > cifs_filldir_unix(struct qstr *pqstring, > FILE_UNIX_INFO * pUnixFindData, struct file *file, >- filldir_t filldir, void *direntry) >+ filldir_t filldir, void *direntry, char * mbFileName ) > { > struct inode *tmp_inode; > struct dentry *tmp_dentry; > int object_type, rc; > >- pqstring->name = pUnixFindData->FileName; >- pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF); >+ if ( mbFileName == NULL ) >+ mbFileName = pUnixFindData->FileName; >+ >+ pqstring->name = mbFileName; >+ pqstring->len = strnlen(mbFileName, MAX_PATHCONF); > > rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); > if((tmp_inode == NULL) || (tmp_dentry == NULL)) { >@@ -1895,12 +1904,12 @@ cifs_filldir_unix(struct qstr *pqstring, > insert_inode_hash(tmp_inode); > } /* else if i_ino has changed should we rehash it? */ > unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type); >- rc = filldir(direntry, pUnixFindData->FileName, pqstring->len, >+ rc = filldir(direntry, mbFileName, pqstring->len, > file->f_pos, tmp_inode->i_ino, object_type); > if(rc) { > /* due to readdir error we need to recalculate resume > key so next readdir will restart on right entry */ >- cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName)); >+ cFYI(1,("Error %d on filldir of %s",rc , mbFileName)); > } > dput(tmp_dentry); > return rc; >@@ -2096,73 +2105,89 @@ cifs_readdir(struct file *file, void *di > cifsFile->resume_name_length); > } > for (i = 2; i < count + 2; i++) { >+ /* unicode conversion buffer */ >+ char convBuf[MAX_PATHCONF]; >+ char *pmbFileName = NULL; >+ > if (UnixSearch == FALSE) { > __u32 len = le32_to_cpu(pfindData->FileNameLength); >+ pmbFileName = pfindData->FileName; > if (Unicode == TRUE) >+ { >+ pmbFileName = convBuf; > len = >- cifs_strfromUCS_le >- (pfindData->FileName, >- (wchar_t *) >- pfindData->FileName, >- len / 2, >- cifs_sb->local_nls); >+ cifs_strfromUCS_le_fitBufLen( >+ pmbFileName, MAX_PATHCONF, >+ (wchar_t *) pfindData->FileName, len / 2, >+ cifs_sb->local_nls); >+ } > qstring.len = len; > if (((len != 1) >- || (pfindData->FileName[0] != '.')) >+ || (pmbFileName[0] != '.')) > && ((len != 2) >- || (pfindData-> >- FileName[0] != '.') >- || (pfindData-> >- FileName[1] != '.'))) { >+ || (pmbFileName[0] != '.') >+ || (pmbFileName[1] != '.'))) { > if(cifs_filldir(&qstring, > pfindData, > file, filldir, >- direntry)) { >+ direntry, pmbFileName)) { > /* do not end search if > kernel not ready to take > remaining entries yet */ >- reset_resume_key(file, pfindData->FileName,qstring.len, >- Unicode, cifs_sb->local_nls); >+ reset_resume_key(file, pfindData->FileName, >+ le32_to_cpu(pfindData->FileNameLength)); > findParms.EndofSearch = 0; > break; > } > file->f_pos++; > } > } else { /* UnixSearch */ >- pfindDataUnix = >- (FILE_UNIX_INFO *) pfindData; >- if (Unicode == TRUE) >+ __u32 len = 0; >+ pfindDataUnix = (FILE_UNIX_INFO *) pfindData; >+ pmbFileName = pfindDataUnix->FileName; >+ /* calculate safe length */ >+ len = le32_to_cpu(pfindDataUnix->NextEntryOffset) >+ - (__u32)(sizeof(FILE_UNIX_INFO)-1); >+ /* trim extra null chars */ >+ if (Unicode == TRUE) { >+ __u32 lenTmp = len/2-1; >+ wchar_t * pwc = (wchar_t*)pfindDataUnix->FileName; >+ while ( lenTmp>1 && pwc[lenTmp-1] == 0 && pwc[lenTmp] == 0 ) >+ lenTmp--; >+ len=lenTmp*2; >+ } else { >+ __u32 lenTmp = len-1; >+ char * pmb = pfindDataUnix->FileName; >+ while ( lenTmp>1 && pmb[lenTmp-1] == 0 && pmb[lenTmp] == 0 ) >+ lenTmp--; >+ len = lenTmp; >+ } >+ >+ if (Unicode == TRUE) { >+ pmbFileName = convBuf; > qstring.len = >- cifs_strfromUCS_le >- (pfindDataUnix->FileName, >- (wchar_t *) >- pfindDataUnix->FileName, >- MAX_PATHCONF, >- cifs_sb->local_nls); >- else >+ cifs_strfromUCS_le_fitBufLen( >+ pmbFileName, MAX_PATHCONF, >+ (wchar_t *) pfindDataUnix->FileName, len / 2, >+ cifs_sb->local_nls); >+ } else > qstring.len = >- strnlen(pfindDataUnix-> >- FileName, >- MAX_PATHCONF); >- if (((qstring.len != 1) >- || (pfindDataUnix-> >- FileName[0] != '.')) >- && ((qstring.len != 2) >- || (pfindDataUnix-> >- FileName[0] != '.') >- || (pfindDataUnix-> >- FileName[1] != '.'))) { >+ strnlen(pmbFileName, len); >+ >+ if (((qstring.len != 1) || (pmbFileName[0] != '.')) >+ && ((qstring.len != 2) || (pmbFileName[0] != '.') >+ || (pmbFileName[1] != '.'))) { > if(cifs_filldir_unix(&qstring, > pfindDataUnix, > file, > filldir, >- direntry)) { >+ direntry, >+ pmbFileName)) { > /* do not end search if > kernel not ready to take > remaining entries yet */ > findParms.EndofSearch = 0; >- reset_resume_key(file, pfindDataUnix->FileName, >- qstring.len,Unicode,cifs_sb->local_nls); >+ reset_resume_key(file, pfindDataUnix->FileName, len ); > break; > } > file->f_pos++; >@@ -2293,77 +2318,88 @@ cifs_readdir(struct file *file, void *di > } > > for (i = 0; i < count; i++) { >- __u32 len = le32_to_cpu(pfindData-> >- FileNameLength); >+ /* unicode conversion buffer */ >+ char convBuf[MAX_PATHCONF]; >+ char *pmbFileName = NULL; >+ > if (UnixSearch == FALSE) { >+ __u32 len = le32_to_cpu(pfindData->FileNameLength); >+ pmbFileName = pfindData->FileName; > if (Unicode == TRUE) >+ { >+ pmbFileName = convBuf; > len = >- cifs_strfromUCS_le >- (pfindData->FileName, >- (wchar_t *) >- pfindData->FileName, >- len / 2, >- cifs_sb->local_nls); >+ cifs_strfromUCS_le_fitBufLen( >+ pmbFileName, MAX_PATHCONF, >+ (wchar_t *)pfindData->FileName, len / 2, >+ cifs_sb->local_nls); >+ } > qstring.len = len; >- if (((len != 1) >- || (pfindData->FileName[0] != '.')) >+ if (((len != 1) || (pmbFileName[0] != '.')) > && ((len != 2) >- || (pfindData->FileName[0] != '.') >- || (pfindData->FileName[1] != >- '.'))) { >+ || (pmbFileName[0] != '.') >+ || (pmbFileName[1] != '.'))) { > if(cifs_filldir > (&qstring, > pfindData, > file, filldir, >- direntry)) { >+ direntry, pmbFileName)) { > /* do not end search if > kernel not ready to take > remaining entries yet */ > findNextParms.EndofSearch = 0; >- reset_resume_key(file, pfindData->FileName,qstring.len, >- Unicode,cifs_sb->local_nls); >+ reset_resume_key(file, pfindData->FileName, >+ le32_to_cpu(pfindData->FileNameLength)); > break; > } > file->f_pos++; > } > } else { /* UnixSearch */ >- pfindDataUnix = >- (FILE_UNIX_INFO *) >- pfindData; >- if (Unicode == TRUE) >+ __u32 len = 0; >+ pfindDataUnix = (FILE_UNIX_INFO *) pfindData; >+ pmbFileName = pfindDataUnix->FileName; >+ /* calculate safe length */ >+ len = le32_to_cpu(pfindDataUnix->NextEntryOffset) >+ - (__u32)(sizeof(FILE_UNIX_INFO)-1); >+ /* trim extra null chars */ >+ if (Unicode == TRUE) { >+ __u32 lenTmp = len/2-1; >+ wchar_t * pwc = (wchar_t*)pfindDataUnix->FileName; >+ while ( lenTmp>1 && pwc[lenTmp-1] == 0 && pwc[lenTmp] == 0 ) >+ lenTmp--; >+ len=lenTmp*2; >+ } else { >+ __u32 lenTmp = len-1; >+ char * pmb = pfindDataUnix->FileName; >+ while ( lenTmp>1 && pmb[lenTmp-1] == 0 && pmb[lenTmp] == 0 ) >+ lenTmp--; >+ len = lenTmp; >+ } >+ >+ if (Unicode == TRUE) { >+ pmbFileName = convBuf; > qstring.len = >- cifs_strfromUCS_le >- (pfindDataUnix->FileName, >- (wchar_t *) >- pfindDataUnix->FileName, >- MAX_PATHCONF, >- cifs_sb->local_nls); >- else >+ cifs_strfromUCS_le_fitBufLen( >+ pmbFileName, MAX_PATHCONF, >+ (wchar_t *)pfindDataUnix->FileName, len / 2, >+ cifs_sb->local_nls); >+ } else > qstring.len = >- strnlen >- (pfindDataUnix-> >- FileName, >- MAX_PATHCONF); >- if (((qstring.len != 1) >- || (pfindDataUnix-> >- FileName[0] != '.')) >- && ((qstring.len != 2) >- || (pfindDataUnix-> >- FileName[0] != '.') >- || (pfindDataUnix-> >- FileName[1] != >- '.'))) { >+ strnlen(pmbFileName, len); >+ >+ if (((qstring.len != 1) || (pmbFileName[0] != '.')) >+ && ((qstring.len != 2) || (pmbFileName[0] != '.') >+ || (pmbFileName[1] != '.'))) { > if(cifs_filldir_unix > (&qstring, > pfindDataUnix, > file, filldir, >- direntry)) { >+ direntry, pmbFileName)) { > /* do not end search if > kernel not ready to take > remaining entries yet */ > findNextParms.EndofSearch = 0; >- reset_resume_key(file, pfindDataUnix->FileName,qstring.len, >- Unicode,cifs_sb->local_nls); >+ reset_resume_key(file, pfindDataUnix->FileName, len ); > break; > } > file->f_pos++;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 2176
:
850
|
851
|
852
| 860