utf16_to_utf8_size() was not guaranteed to fail with ENAMETOOLONG if the computed length was greater than @outs_len. This could cause a buffer overrun in ntfs_utf16_to_utf8(). This was a bug introduced by the patches to allow broken Unicode. Fix it.
Signed-off-by: Eric Biggers <ebigge...@gmail.com> --- libntfs-3g/unistr.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/libntfs-3g/unistr.c b/libntfs-3g/unistr.c index 4d33bb4..190dbd8 100644 --- a/libntfs-3g/unistr.c +++ b/libntfs-3g/unistr.c @@ -458,10 +458,15 @@ void ntfs_file_value_upcase(FILE_NAME_ATTR *file_name_attr, */ /* - * Return the amount of 8-bit elements in UTF-8 needed (without the terminating - * null) to store a given UTF-16LE string. + * Return the number of bytes in UTF-8 needed (without the terminating null) to + * store the given UTF-16LE string. * - * Return -1 with errno set if string has invalid byte sequence or too long. + * On error, -1 is returned, and errno is set to the error code. The following + * error codes can be expected: + * EILSEQ The input string is not valid UTF-16LE (only possible + * if compiled without ALLOW_BROKEN_UNICODE). + * ENAMETOOLONG The length of the UTF-8 string in bytes (without the + * terminating null) would exceed @outs_len. */ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_len) { @@ -470,7 +475,7 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l BOOL surrog; surrog = FALSE; - for (i = 0; i < ins_len && ins[i]; i++) { + for (i = 0; i < ins_len && ins[i] && count <= outs_len; i++) { unsigned short c = le16_to_cpu(ins[i]); if (surrog) { if ((c >= 0xdc00) && (c < 0xe000)) { @@ -511,17 +516,20 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l count += 3; else goto fail; - if (count > outs_len) { - errno = ENAMETOOLONG; - goto out; - } } - if (surrog) + + if (surrog && count <= outs_len) { #if ALLOW_BROKEN_UNICODE count += 3; /* ending with a single surrogate */ #else goto fail; #endif /* ALLOW_BROKEN_UNICODE */ + } + + if (count > outs_len) { + errno = ENAMETOOLONG; + goto out; + } ret = count; out: -- 2.9.3 ------------------------------------------------------------------------------ _______________________________________________ ntfs-3g-devel mailing list ntfs-3g-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ntfs-3g-devel