unicode.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Some of the source code in this file came from fs/cifs/cifs_unicode.c
  4. *
  5. * Copyright (c) International Business Machines Corp., 2000,2009
  6. * Modified by Steve French (sfrench@us.ibm.com)
  7. * Modified by Namjae Jeon (linkinjeon@kernel.org)
  8. */
  9. #include <linux/fs.h>
  10. #include <linux/slab.h>
  11. #include <linux/unaligned.h>
  12. #include "glob.h"
  13. #include "unicode.h"
  14. #include "smb_common.h"
  15. /*
  16. * cifs_mapchar() - convert a host-endian char to proper char in codepage
  17. * @target: where converted character should be copied
  18. * @from: host-endian source string
  19. * @cp: codepage to which character should be converted
  20. * @mapchar: should character be mapped according to mapchars mount option?
  21. *
  22. * This function handles the conversion of a single character. It is the
  23. * responsibility of the caller to ensure that the target buffer is large
  24. * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
  25. *
  26. * Return: string length after conversion
  27. */
  28. static int
  29. cifs_mapchar(char *target, const __u16 *from, const struct nls_table *cp,
  30. bool mapchar)
  31. {
  32. int len = 1;
  33. __u16 src_char;
  34. src_char = *from;
  35. if (!mapchar)
  36. goto cp_convert;
  37. /*
  38. * BB: Cannot handle remapping UNI_SLASH until all the calls to
  39. * build_path_from_dentry are modified, as they use slash as
  40. * separator.
  41. */
  42. switch (src_char) {
  43. case UNI_COLON:
  44. *target = ':';
  45. break;
  46. case UNI_ASTERISK:
  47. *target = '*';
  48. break;
  49. case UNI_QUESTION:
  50. *target = '?';
  51. break;
  52. case UNI_PIPE:
  53. *target = '|';
  54. break;
  55. case UNI_GRTRTHAN:
  56. *target = '>';
  57. break;
  58. case UNI_LESSTHAN:
  59. *target = '<';
  60. break;
  61. default:
  62. goto cp_convert;
  63. }
  64. out:
  65. return len;
  66. cp_convert:
  67. len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE);
  68. if (len <= 0)
  69. goto surrogate_pair;
  70. goto out;
  71. surrogate_pair:
  72. /* convert SURROGATE_PAIR and IVS */
  73. if (strcmp(cp->charset, "utf8"))
  74. goto unknown;
  75. len = utf16s_to_utf8s(from, 3, UTF16_LITTLE_ENDIAN, target, 6);
  76. if (len <= 0)
  77. goto unknown;
  78. return len;
  79. unknown:
  80. *target = '?';
  81. len = 1;
  82. goto out;
  83. }
  84. /*
  85. * smb_utf16_bytes() - compute converted string length
  86. * @from: pointer to input string
  87. * @maxbytes: input string length
  88. * @codepage: destination codepage
  89. *
  90. * Walk a utf16le string and return the number of bytes that the string will
  91. * be after being converted to the given charset, not including any null
  92. * termination required. Don't walk past maxbytes in the source buffer.
  93. *
  94. * Return: string length after conversion
  95. */
  96. static int smb_utf16_bytes(const __le16 *from, int maxbytes,
  97. const struct nls_table *codepage)
  98. {
  99. int i, j;
  100. int charlen, outlen = 0;
  101. int maxwords = maxbytes / 2;
  102. char tmp[NLS_MAX_CHARSET_SIZE];
  103. __u16 ftmp[3];
  104. for (i = 0; i < maxwords; i++) {
  105. ftmp[0] = get_unaligned_le16(&from[i]);
  106. if (ftmp[0] == 0)
  107. break;
  108. for (j = 1; j <= 2; j++) {
  109. if (i + j < maxwords)
  110. ftmp[j] = get_unaligned_le16(&from[i + j]);
  111. else
  112. ftmp[j] = 0;
  113. }
  114. charlen = cifs_mapchar(tmp, ftmp, codepage, 0);
  115. if (charlen > 0)
  116. outlen += charlen;
  117. else
  118. outlen++;
  119. }
  120. return outlen;
  121. }
  122. /*
  123. * smb_from_utf16() - convert utf16le string to local charset
  124. * @to: destination buffer
  125. * @from: source buffer
  126. * @tolen: destination buffer size (in bytes)
  127. * @fromlen: source buffer size (in bytes)
  128. * @codepage: codepage to which characters should be converted
  129. * @mapchar: should characters be remapped according to the mapchars option?
  130. *
  131. * Convert a little-endian utf16le string (as sent by the server) to a string
  132. * in the provided codepage. The tolen and fromlen parameters are to ensure
  133. * that the code doesn't walk off of the end of the buffer (which is always
  134. * a danger if the alignment of the source buffer is off). The destination
  135. * string is always properly null terminated and fits in the destination
  136. * buffer. Returns the length of the destination string in bytes (including
  137. * null terminator).
  138. *
  139. * Note that some windows versions actually send multiword UTF-16 characters
  140. * instead of straight UTF16-2. The linux nls routines however aren't able to
  141. * deal with those characters properly. In the event that we get some of
  142. * those characters, they won't be translated properly.
  143. *
  144. * Return: string length after conversion
  145. */
  146. static int smb_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
  147. const struct nls_table *codepage, bool mapchar)
  148. {
  149. int i, j, charlen, safelen;
  150. int outlen = 0;
  151. int nullsize = nls_nullsize(codepage);
  152. int fromwords = fromlen / 2;
  153. char tmp[NLS_MAX_CHARSET_SIZE];
  154. __u16 ftmp[3]; /* ftmp[3] = 3array x 2bytes = 6bytes UTF-16 */
  155. /*
  156. * because the chars can be of varying widths, we need to take care
  157. * not to overflow the destination buffer when we get close to the
  158. * end of it. Until we get to this offset, we don't need to check
  159. * for overflow however.
  160. */
  161. safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
  162. for (i = 0; i < fromwords; i++) {
  163. ftmp[0] = get_unaligned_le16(&from[i]);
  164. if (ftmp[0] == 0)
  165. break;
  166. for (j = 1; j <= 2; j++) {
  167. if (i + j < fromwords)
  168. ftmp[j] = get_unaligned_le16(&from[i + j]);
  169. else
  170. ftmp[j] = 0;
  171. }
  172. /*
  173. * check to see if converting this character might make the
  174. * conversion bleed into the null terminator
  175. */
  176. if (outlen >= safelen) {
  177. charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar);
  178. if ((outlen + charlen) > (tolen - nullsize))
  179. break;
  180. }
  181. /* put converted char into 'to' buffer */
  182. charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar);
  183. outlen += charlen;
  184. /*
  185. * charlen (=bytes of UTF-8 for 1 character)
  186. * 4bytes UTF-8(surrogate pair) is charlen=4
  187. * (4bytes UTF-16 code)
  188. * 7-8bytes UTF-8(IVS) is charlen=3+4 or 4+4
  189. * (2 UTF-8 pairs divided to 2 UTF-16 pairs)
  190. */
  191. if (charlen == 4)
  192. i++;
  193. else if (charlen >= 5)
  194. /* 5-6bytes UTF-8 */
  195. i += 2;
  196. }
  197. /* properly null-terminate string */
  198. for (i = 0; i < nullsize; i++)
  199. to[outlen++] = 0;
  200. return outlen;
  201. }
  202. /*
  203. * smb_strtoUTF16() - Convert character string to unicode string
  204. * @to: destination buffer
  205. * @from: source buffer
  206. * @len: destination buffer size (in bytes)
  207. * @codepage: codepage to which characters should be converted
  208. *
  209. * Return: string length after conversion
  210. */
  211. int smb_strtoUTF16(__le16 *to, const char *from, int len,
  212. const struct nls_table *codepage)
  213. {
  214. int charlen;
  215. int i;
  216. wchar_t wchar_to; /* needed to quiet sparse */
  217. /* special case for utf8 to handle no plane0 chars */
  218. if (!strcmp(codepage->charset, "utf8")) {
  219. /*
  220. * convert utf8 -> utf16, we assume we have enough space
  221. * as caller should have assumed conversion does not overflow
  222. * in destination len is length in wchar_t units (16bits)
  223. */
  224. i = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN,
  225. (wchar_t *)to, len);
  226. /* if success terminate and exit */
  227. if (i >= 0)
  228. goto success;
  229. /*
  230. * if fails fall back to UCS encoding as this
  231. * function should not return negative values
  232. * currently can fail only if source contains
  233. * invalid encoded characters
  234. */
  235. }
  236. for (i = 0; len > 0 && *from; i++, from += charlen, len -= charlen) {
  237. charlen = codepage->char2uni(from, len, &wchar_to);
  238. if (charlen < 1) {
  239. /* A question mark */
  240. wchar_to = 0x003f;
  241. charlen = 1;
  242. }
  243. put_unaligned_le16(wchar_to, &to[i]);
  244. }
  245. success:
  246. put_unaligned_le16(0, &to[i]);
  247. return i;
  248. }
  249. /*
  250. * smb_strndup_from_utf16() - copy a string from wire format to the local
  251. * codepage
  252. * @src: source string
  253. * @maxlen: don't walk past this many bytes in the source string
  254. * @is_unicode: is this a unicode string?
  255. * @codepage: destination codepage
  256. *
  257. * Take a string given by the server, convert it to the local codepage and
  258. * put it in a new buffer. Returns a pointer to the new string or NULL on
  259. * error.
  260. *
  261. * Return: destination string buffer or error ptr
  262. */
  263. char *smb_strndup_from_utf16(const char *src, const int maxlen,
  264. const bool is_unicode,
  265. const struct nls_table *codepage)
  266. {
  267. int len, ret;
  268. char *dst;
  269. if (is_unicode) {
  270. len = smb_utf16_bytes((__le16 *)src, maxlen, codepage);
  271. len += nls_nullsize(codepage);
  272. dst = kmalloc(len, KSMBD_DEFAULT_GFP);
  273. if (!dst)
  274. return ERR_PTR(-ENOMEM);
  275. ret = smb_from_utf16(dst, (__le16 *)src, len, maxlen, codepage,
  276. false);
  277. if (ret < 0) {
  278. kfree(dst);
  279. return ERR_PTR(-EINVAL);
  280. }
  281. } else {
  282. len = strnlen(src, maxlen);
  283. len++;
  284. dst = kmalloc(len, KSMBD_DEFAULT_GFP);
  285. if (!dst)
  286. return ERR_PTR(-ENOMEM);
  287. strscpy(dst, src, len);
  288. }
  289. return dst;
  290. }
  291. /*
  292. * Convert 16 bit Unicode pathname to wire format from string in current code
  293. * page. Conversion may involve remapping up the six characters that are
  294. * only legal in POSIX-like OS (if they are present in the string). Path
  295. * names are little endian 16 bit Unicode on the wire
  296. */
  297. /*
  298. * smbConvertToUTF16() - convert string from local charset to utf16
  299. * @target: destination buffer
  300. * @source: source buffer
  301. * @srclen: source buffer size (in bytes)
  302. * @cp: codepage to which characters should be converted
  303. * @mapchar: should characters be remapped according to the mapchars option?
  304. *
  305. * Convert 16 bit Unicode pathname to wire format from string in current code
  306. * page. Conversion may involve remapping up the six characters that are
  307. * only legal in POSIX-like OS (if they are present in the string). Path
  308. * names are little endian 16 bit Unicode on the wire
  309. *
  310. * Return: char length after conversion
  311. */
  312. int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
  313. const struct nls_table *cp, int mapchars)
  314. {
  315. int i, j, charlen;
  316. char src_char;
  317. __le16 dst_char;
  318. wchar_t tmp;
  319. wchar_t wchar_to[6]; /* UTF-16 */
  320. int ret;
  321. unicode_t u;
  322. if (!mapchars)
  323. return smb_strtoUTF16(target, source, srclen, cp);
  324. for (i = 0, j = 0; i < srclen; j++) {
  325. src_char = source[i];
  326. charlen = 1;
  327. switch (src_char) {
  328. case 0:
  329. put_unaligned(0, &target[j]);
  330. return j;
  331. case ':':
  332. dst_char = cpu_to_le16(UNI_COLON);
  333. break;
  334. case '*':
  335. dst_char = cpu_to_le16(UNI_ASTERISK);
  336. break;
  337. case '?':
  338. dst_char = cpu_to_le16(UNI_QUESTION);
  339. break;
  340. case '<':
  341. dst_char = cpu_to_le16(UNI_LESSTHAN);
  342. break;
  343. case '>':
  344. dst_char = cpu_to_le16(UNI_GRTRTHAN);
  345. break;
  346. case '|':
  347. dst_char = cpu_to_le16(UNI_PIPE);
  348. break;
  349. /*
  350. * FIXME: We can not handle remapping backslash (UNI_SLASH)
  351. * until all the calls to build_path_from_dentry are modified,
  352. * as they use backslash as separator.
  353. */
  354. default:
  355. charlen = cp->char2uni(source + i, srclen - i, &tmp);
  356. dst_char = cpu_to_le16(tmp);
  357. /*
  358. * if no match, use question mark, which at least in
  359. * some cases serves as wild card
  360. */
  361. if (charlen > 0)
  362. goto ctoUTF16;
  363. /* convert SURROGATE_PAIR */
  364. if (strcmp(cp->charset, "utf8"))
  365. goto unknown;
  366. if (*(source + i) & 0x80) {
  367. charlen = utf8_to_utf32(source + i, 6, &u);
  368. if (charlen < 0)
  369. goto unknown;
  370. } else
  371. goto unknown;
  372. ret = utf8s_to_utf16s(source + i, charlen,
  373. UTF16_LITTLE_ENDIAN,
  374. wchar_to, 6);
  375. if (ret < 0)
  376. goto unknown;
  377. i += charlen;
  378. dst_char = cpu_to_le16(*wchar_to);
  379. if (charlen <= 3)
  380. /* 1-3bytes UTF-8 to 2bytes UTF-16 */
  381. put_unaligned(dst_char, &target[j]);
  382. else if (charlen == 4) {
  383. /*
  384. * 4bytes UTF-8(surrogate pair) to 4bytes UTF-16
  385. * 7-8bytes UTF-8(IVS) divided to 2 UTF-16
  386. * (charlen=3+4 or 4+4)
  387. */
  388. put_unaligned(dst_char, &target[j]);
  389. dst_char = cpu_to_le16(*(wchar_to + 1));
  390. j++;
  391. put_unaligned(dst_char, &target[j]);
  392. } else if (charlen >= 5) {
  393. /* 5-6bytes UTF-8 to 6bytes UTF-16 */
  394. put_unaligned(dst_char, &target[j]);
  395. dst_char = cpu_to_le16(*(wchar_to + 1));
  396. j++;
  397. put_unaligned(dst_char, &target[j]);
  398. dst_char = cpu_to_le16(*(wchar_to + 2));
  399. j++;
  400. put_unaligned(dst_char, &target[j]);
  401. }
  402. continue;
  403. unknown:
  404. dst_char = cpu_to_le16(0x003f);
  405. charlen = 1;
  406. }
  407. ctoUTF16:
  408. /*
  409. * character may take more than one byte in the source string,
  410. * but will take exactly two bytes in the target string
  411. */
  412. i += charlen;
  413. put_unaligned(dst_char, &target[j]);
  414. }
  415. return j;
  416. }