diff options
author | Frediano Ziglio <frediano.ziglio@citrix.com> | 2012-08-07 05:33:03 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-10-07 21:04:53 -0400 |
commit | fd3ba42c76d3d4b776120c2b24c1791e7bb3deb1 (patch) | |
tree | 1e08474b01069313451fc646e2b4a236029598d5 /fs/cifs/cifs_unicode.c | |
parent | b7a10626c8bc88fd097a8bb4486c89558f89320c (diff) |
Convert properly UTF-8 to UTF-16
wchar_t is currently 16bit so converting a utf8 encoded characters not
in plane 0 (>= 0x10000) to wchar_t (that is calling char2uni) lead to a
-EINVAL return. This patch detect utf8 in cifs_strtoUTF16 and add special
code calling utf8s_to_utf16s.
Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
Acked-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/cifs_unicode.c')
-rw-r--r-- | fs/cifs/cifs_unicode.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 53cf2aabce87..71d5d0a5f6b2 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c | |||
@@ -203,6 +203,27 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, | |||
203 | int i; | 203 | int i; |
204 | wchar_t wchar_to; /* needed to quiet sparse */ | 204 | wchar_t wchar_to; /* needed to quiet sparse */ |
205 | 205 | ||
206 | /* special case for utf8 to handle no plane0 chars */ | ||
207 | if (!strcmp(codepage->charset, "utf8")) { | ||
208 | /* | ||
209 | * convert utf8 -> utf16, we assume we have enough space | ||
210 | * as caller should have assumed conversion does not overflow | ||
211 | * in destination len is length in wchar_t units (16bits) | ||
212 | */ | ||
213 | i = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN, | ||
214 | (wchar_t *) to, len); | ||
215 | |||
216 | /* if success terminate and exit */ | ||
217 | if (i >= 0) | ||
218 | goto success; | ||
219 | /* | ||
220 | * if fails fall back to UCS encoding as this | ||
221 | * function should not return negative values | ||
222 | * currently can fail only if source contains | ||
223 | * invalid encoded characters | ||
224 | */ | ||
225 | } | ||
226 | |||
206 | for (i = 0; len && *from; i++, from += charlen, len -= charlen) { | 227 | for (i = 0; len && *from; i++, from += charlen, len -= charlen) { |
207 | charlen = codepage->char2uni(from, len, &wchar_to); | 228 | charlen = codepage->char2uni(from, len, &wchar_to); |
208 | if (charlen < 1) { | 229 | if (charlen < 1) { |
@@ -215,6 +236,7 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, | |||
215 | put_unaligned_le16(wchar_to, &to[i]); | 236 | put_unaligned_le16(wchar_to, &to[i]); |
216 | } | 237 | } |
217 | 238 | ||
239 | success: | ||
218 | put_unaligned_le16(0, &to[i]); | 240 | put_unaligned_le16(0, &to[i]); |
219 | return i; | 241 | return i; |
220 | } | 242 | } |