cifs: fix unaligned accesses in cifsConvertToUCS
Move cifsConvertToUCS to cifs_unicode.c where all of the other unicode related functions live. Have it store mapped characters in 'temp' and then use put_unaligned_le16 to copy it to the target buffer. Also fix the comments to match kernel coding style. Signed-off-by: Jeff Layton <jlayton@redhat.com> Acked-by: Pavel Shilovsky <piastryyy@gmail.com> Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
		
					parent
					
						
							
								ba2dbf30df
							
						
					
				
			
			
				commit
				
					
						84cdf74e80
					
				
			
		
					 2 changed files with 76 additions and 71 deletions
				
			
		|  | @ -257,3 +257,79 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode, | ||||||
| 	return dst; | 	return dst; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Convert 16 bit Unicode pathname to wire format from string in current code | ||||||
|  |  * page. Conversion may involve remapping up the six characters that are | ||||||
|  |  * only legal in POSIX-like OS (if they are present in the string). Path | ||||||
|  |  * names are little endian 16 bit Unicode on the wire | ||||||
|  |  */ | ||||||
|  | int | ||||||
|  | cifsConvertToUCS(__le16 *target, const char *source, int maxlen, | ||||||
|  | 		 const struct nls_table *cp, int mapChars) | ||||||
|  | { | ||||||
|  | 	int i, j, charlen; | ||||||
|  | 	int len_remaining = maxlen; | ||||||
|  | 	char src_char; | ||||||
|  | 	__u16 temp; | ||||||
|  | 
 | ||||||
|  | 	if (!mapChars) | ||||||
|  | 		return cifs_strtoUCS(target, source, PATH_MAX, cp); | ||||||
|  | 
 | ||||||
|  | 	for (i = 0, j = 0; i < maxlen; j++) { | ||||||
|  | 		src_char = source[i]; | ||||||
|  | 		switch (src_char) { | ||||||
|  | 		case 0: | ||||||
|  | 			put_unaligned_le16(0, &target[j]); | ||||||
|  | 			goto ctoUCS_out; | ||||||
|  | 		case ':': | ||||||
|  | 			temp = UNI_COLON; | ||||||
|  | 			break; | ||||||
|  | 		case '*': | ||||||
|  | 			temp = UNI_ASTERIK; | ||||||
|  | 			break; | ||||||
|  | 		case '?': | ||||||
|  | 			temp = UNI_QUESTION; | ||||||
|  | 			break; | ||||||
|  | 		case '<': | ||||||
|  | 			temp = UNI_LESSTHAN; | ||||||
|  | 			break; | ||||||
|  | 		case '>': | ||||||
|  | 			temp = UNI_GRTRTHAN; | ||||||
|  | 			break; | ||||||
|  | 		case '|': | ||||||
|  | 			temp = UNI_PIPE; | ||||||
|  | 			break; | ||||||
|  | 		/*
 | ||||||
|  | 		 * FIXME: We can not handle remapping backslash (UNI_SLASH) | ||||||
|  | 		 * until all the calls to build_path_from_dentry are modified, | ||||||
|  | 		 * as they use backslash as separator. | ||||||
|  | 		 */ | ||||||
|  | 		default: | ||||||
|  | 			charlen = cp->char2uni(source+i, len_remaining, | ||||||
|  | 						&temp); | ||||||
|  | 			/*
 | ||||||
|  | 			 * if no match, use question mark, which at least in | ||||||
|  | 			 * some cases serves as wild card | ||||||
|  | 			 */ | ||||||
|  | 			if (charlen < 1) { | ||||||
|  | 				temp = 0x003f; | ||||||
|  | 				charlen = 1; | ||||||
|  | 			} | ||||||
|  | 			len_remaining -= charlen; | ||||||
|  | 			/*
 | ||||||
|  | 			 * character may take more than one byte in the source | ||||||
|  | 			 * string, but will take exactly two bytes in the | ||||||
|  | 			 * target string | ||||||
|  | 			 */ | ||||||
|  | 			i += charlen; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		put_unaligned_le16(temp, &target[j]); | ||||||
|  | 		i++; /* move to next char in source string */ | ||||||
|  | 		len_remaining--; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | ctoUCS_out: | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -637,77 +637,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) | ||||||
| 	return; | 	return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Convert 16 bit Unicode pathname to wire format from string in current code
 |  | ||||||
|    page.  Conversion may involve remapping up the seven characters that are |  | ||||||
|    only legal in POSIX-like OS (if they are present in the string). Path |  | ||||||
|    names are little endian 16 bit Unicode on the wire */ |  | ||||||
| int |  | ||||||
| cifsConvertToUCS(__le16 *target, const char *source, int maxlen, |  | ||||||
| 		 const struct nls_table *cp, int mapChars) |  | ||||||
| { |  | ||||||
| 	int i, j, charlen; |  | ||||||
| 	int len_remaining = maxlen; |  | ||||||
| 	char src_char; |  | ||||||
| 	__u16 temp; |  | ||||||
| 
 |  | ||||||
| 	if (!mapChars) |  | ||||||
| 		return cifs_strtoUCS(target, source, PATH_MAX, cp); |  | ||||||
| 
 |  | ||||||
| 	for (i = 0, j = 0; i < maxlen; j++) { |  | ||||||
| 		src_char = source[i]; |  | ||||||
| 		switch (src_char) { |  | ||||||
| 			case 0: |  | ||||||
| 				target[j] = 0; |  | ||||||
| 				goto ctoUCS_out; |  | ||||||
| 			case ':': |  | ||||||
| 				target[j] = cpu_to_le16(UNI_COLON); |  | ||||||
| 				break; |  | ||||||
| 			case '*': |  | ||||||
| 				target[j] = cpu_to_le16(UNI_ASTERIK); |  | ||||||
| 				break; |  | ||||||
| 			case '?': |  | ||||||
| 				target[j] = cpu_to_le16(UNI_QUESTION); |  | ||||||
| 				break; |  | ||||||
| 			case '<': |  | ||||||
| 				target[j] = cpu_to_le16(UNI_LESSTHAN); |  | ||||||
| 				break; |  | ||||||
| 			case '>': |  | ||||||
| 				target[j] = cpu_to_le16(UNI_GRTRTHAN); |  | ||||||
| 				break; |  | ||||||
| 			case '|': |  | ||||||
| 				target[j] = cpu_to_le16(UNI_PIPE); |  | ||||||
| 				break; |  | ||||||
| 			/* BB We can not handle remapping slash until
 |  | ||||||
| 			   all the calls to build_path_from_dentry |  | ||||||
| 			   are modified, as they use slash as separator BB */ |  | ||||||
| 			/* case '\\':
 |  | ||||||
| 				target[j] = cpu_to_le16(UNI_SLASH); |  | ||||||
| 				break;*/ |  | ||||||
| 			default: |  | ||||||
| 				charlen = cp->char2uni(source+i, |  | ||||||
| 					len_remaining, &temp); |  | ||||||
| 				/* if no match, use question mark, which
 |  | ||||||
| 				at least in some cases servers as wild card */ |  | ||||||
| 				if (charlen < 1) { |  | ||||||
| 					target[j] = cpu_to_le16(0x003f); |  | ||||||
| 					charlen = 1; |  | ||||||
| 				} else |  | ||||||
| 					target[j] = cpu_to_le16(temp); |  | ||||||
| 				len_remaining -= charlen; |  | ||||||
| 				/* character may take more than one byte in the
 |  | ||||||
| 				   the source string, but will take exactly two |  | ||||||
| 				   bytes in the target string */ |  | ||||||
| 				i += charlen; |  | ||||||
| 				continue; |  | ||||||
| 		} |  | ||||||
| 		i++; /* move to next char in source string */ |  | ||||||
| 		len_remaining--; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| ctoUCS_out: |  | ||||||
| 	return i; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void | void | ||||||
| cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) | cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) | ||||||
| { | { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeff Layton
				Jeff Layton