Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fs/nls: Fix utf16 to utf8 conversion

Currently the function responsible for converting between utf16 and
utf8 strings will ignore any characters that cannot be converted. This
however also includes multi-byte characters that do not fit into the
provided string buffer.

This can cause problems if such a multi-byte character is followed by
a single-byte character. In such a case the multi-byte character might
be ignored when the provided string buffer is too small, but the
single-byte character might fit and is thus still copied into the
resulting string.

Fix this by stop filling the provided string buffer once a character
does not fit. In order to be able to do this extend utf32_to_utf8()
to return useful errno codes instead of -1.

Fixes: 74675a58507e ("NLS: update handling of Unicode")
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://patch.msgid.link/20251111131125.3379-2-W_Armin@gmx.de
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

authored by

Armin Wolf and committed by
Ilpo Järvinen
25524b61 39ae6c50

+12 -4
+12 -4
fs/nls/nls_base.c
··· 94 94 95 95 l = u; 96 96 if (l > UNICODE_MAX || (l & SURROGATE_MASK) == SURROGATE_PAIR) 97 - return -1; 97 + return -EILSEQ; 98 98 99 99 nc = 0; 100 100 for (t = utf8_table; t->cmask && maxout; t++, maxout--) { ··· 110 110 return nc; 111 111 } 112 112 } 113 - return -1; 113 + return -EOVERFLOW; 114 114 } 115 115 EXPORT_SYMBOL(utf32_to_utf8); 116 116 ··· 217 217 inlen--; 218 218 } 219 219 size = utf32_to_utf8(u, op, maxout); 220 - if (size == -1) { 221 - /* Ignore character and move on */ 220 + if (size < 0) { 221 + if (size == -EILSEQ) { 222 + /* Ignore character and move on */ 223 + continue; 224 + } 225 + /* 226 + * Stop filling the buffer with data once a character 227 + * does not fit anymore. 228 + */ 229 + break; 222 230 } else { 223 231 op += size; 224 232 maxout -= size;