ls: fix handling of broken unicode sequences
No binary (build failed)
—
(log yok)
| @@ -139,6 +139,8 @@ size_t FAST_FUNC wcstombs(char *dest, const wchar_t *src, size_t n) | |
| return org_n - n; | |
| } | |
| + | #define ERROR_WCHAR (~(wchar_t)0) |
| + | |
| static const char *mbstowc_internal(wchar_t *res, const char *src) | |
| { | |
| int bytes; | |
| @@ -159,16 +161,22 @@ static const char *mbstowc_internal(wchar_t *res, const char *src) | |
| c <<= 1; | |
| bytes++; | |
| } while ((c & 0x80) && bytes < 6); | |
| - | if (bytes == 1) |
| - | return NULL; |
| + | if (bytes == 1) { |
| + | /* A bare "continuation" byte. Say, 80 */ |
| + | *res = ERROR_WCHAR; |
| + | return src; |
| + | } |
| c = (uint8_t)(c) >> bytes; | |
| while (--bytes) { | |
| - | unsigned ch = (unsigned char) *src++; |
| + | unsigned ch = (unsigned char) *src; |
| if ((ch & 0xc0) != 0x80) { | |
| - | return NULL; |
| + | /* Missing "continuation" byte. Example: e0 80 */ |
| + | *res = ERROR_WCHAR; |
| + | return src; |
| } | |
| c = (c << 6) + (ch & 0x3f); | |
| + | src++; |
| } | |
| /* TODO */ | |
| @@ -177,8 +185,8 @@ static const char *mbstowc_internal(wchar_t *res, const char *src) | |
| /* 11110000 10000000 10000100 10000000 converts to 0x100 */ | |
| /* correct encoding: 11000100 10000000 */ | |
| if (c <= 0x7f) { /* crude check */ | |
| - | return NULL; |
| - | //or maybe 0xfffd; /* replacement character */ |
| + | *res = ERROR_WCHAR; |
| + | return src; |
| } | |
| *res = c; | |
| @@ -204,7 +212,7 @@ size_t FAST_FUNC mbstowcs(wchar_t *dest, const char *src, size_t n) | |
| while (n) { | |
| wchar_t wc; | |
| src = mbstowc_internal(&wc, src); | |
| - | if (src == NULL) /* error */ |
| + | if (wc == ERROR_WCHAR) /* error */ |
| return (size_t) -1L; | |
| if (dest) | |
| *dest++ = wc; | |
| @@ -312,20 +320,15 @@ static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t *stats, const char | |
| goto subst; | |
| } | |
| #else | |
| - | { |
| - | const char *src1 = mbstowc_internal(&wc, src); |
| - | /* src = NULL: invalid sequence is seen, |
| - | * else: wc is set, src is advanced to next mb char |
| - | */ |
| - | if (src1) { /* no error */ |
| - | if (wc == 0) /* end-of-string */ |
| - | break; |
| - | src = src1; |
| - | } else { /* error */ |
| - | src++; |
| - | goto subst; |
| - | } |
| - | } |
| + | src = mbstowc_internal(&wc, src); |
| + | /* src is advanced to next mb char |
| + | * wc == ERROR_WCHAR: invalid sequence is seen |
| + | * else: wc is set |
| + | */ |
| + | if (wc == ERROR_WCHAR) /* error */ |
| + | goto subst; |
| + | if (wc == 0) /* end-of-string */ |
| + | break; |
| #endif | |
| if (CONFIG_LAST_SUPPORTED_WCHAR && wc > CONFIG_LAST_SUPPORTED_WCHAR) | |
| goto subst; | |
| @@ -411,7 +414,7 @@ unsigned FAST_FUNC unicode_padding_to_width(unsigned width, const char *src) | |
| } | |
| #else | |
| src = mbstowc_internal(&wc, src); | |
| - | if (!src || wc == 0) /* error, or end-of-string */ |
| + | if (wc == ERROR_WCHAR || wc == 0) /* error, or end-of-string */ |
| return width; | |
| #endif | |
| w = wcwidth(wc); | |
| @@ -11,9 +11,11 @@ mkdir ls.testdir || exit 1 | |
| # testing "test name" "command" "expected result" "file input" "stdin" | |
| - | # The test isn't passing correctly now - all | chars should line up |
| - | # perfectly in the correctly passed test. |
| + | # With Unicode provided by libc locale, I'm not sure this test can pass. |
| + | # I suspect we might fail to skip exactly correct number of bytes |
| + | # over broked unicode sequences. |
| test x"$CONFIG_FEATURE_ASSUME_UNICODE" = x"y" \ | |
| + | && test x"$CONFIG_LOCALE_SUPPORT" != x"y" \ |
| && test x"$CONFIG_SUBST_WCHAR" = x"63" \ | |
| && test x"$CONFIG_LAST_SUPPORTED_WCHAR" = x"767" \ | |
| && testing "ls unicode test" \ | |
| @@ -73,40 +75,40 @@ test x"$CONFIG_FEATURE_ASSUME_UNICODE" = x"y" \ | |
| 0053____"?_?_"____________________________________________________________| | |
| 0054_3.3__Sequences_with_last_continuation_byte_missing___________________| | |
| 0055_3.3.1__2-byte_sequence_with_last_byte_missing__U+0000_:_____"?"______| | |
| - | 0056_3.3.2__3-byte_sequence_with_last_byte_missing__U+0000_:_____"??"______| |
| - | 0057_3.3.3__4-byte_sequence_with_last_byte_missing__U+0000_:_____"???"______| |
| - | 0058_3.3.4__5-byte_sequence_with_last_byte_missing__U+0000_:_____"????"______| |
| - | 0059_3.3.5__6-byte_sequence_with_last_byte_missing__U+0000_:_____"?????"______| |
| + | 0056_3.3.2__3-byte_sequence_with_last_byte_missing__U+0000_:_____"?"______| |
| + | 0057_3.3.3__4-byte_sequence_with_last_byte_missing__U+0000_:_____"?"______| |
| + | 0058_3.3.4__5-byte_sequence_with_last_byte_missing__U+0000_:_____"?"______| |
| + | 0059_3.3.5__6-byte_sequence_with_last_byte_missing__U+0000_:_____"?"______| |
| 0060_3.3.6__2-byte_sequence_with_last_byte_missing__U-000007FF_:_"?"______| | |
| - | 0061_3.3.7__3-byte_sequence_with_last_byte_missing__U-0000FFFF_:_"??"______| |
| - | 0062_3.3.8__4-byte_sequence_with_last_byte_missing__U-001FFFFF_:_"???"______| |
| - | 0063_3.3.9__5-byte_sequence_with_last_byte_missing__U-03FFFFFF_:_"????"______| |
| - | 0064_3.3.10_6-byte_sequence_with_last_byte_missing__U-7FFFFFFF_:_"?????"______| |
| + | 0061_3.3.7__3-byte_sequence_with_last_byte_missing__U-0000FFFF_:_"?"______| |
| + | 0062_3.3.8__4-byte_sequence_with_last_byte_missing__U-001FFFFF_:_"?"______| |
| + | 0063_3.3.9__5-byte_sequence_with_last_byte_missing__U-03FFFFFF_:_"?"______| |
| + | 0064_3.3.10_6-byte_sequence_with_last_byte_missing__U-7FFFFFFF_:_"?"______| |
| 0065_3.4__Concatenation_of_incomplete_sequences___________________________| | |
| - | 0066____"??????????????????????????????"______________________________________________________| |
| + | 0066____"??????????"______________________________________________________| |
| 0067_3.5__Impossible_bytes________________________________________________| | |
| 0068_3.5.1__fe_=_"?"______________________________________________________| | |
| 0069_3.5.2__ff_=_"?"______________________________________________________| | |
| 0070_3.5.3__fe_fe_ff_ff_=_"????"__________________________________________| | |
| 0071_4__Overlong_sequences________________________________________________| | |
| 0072_4.1__Examples_of_an_overlong_ASCII_character_________________________| | |
| - | 0073_4.1.1_U+002F_=_c0_af_____________=_"??"_______________________________| |
| - | 0074_4.1.2_U+002F_=_e0_80_af__________=_"???"_______________________________| |
| - | 0075_4.1.3_U+002F_=_f0_80_80_af_______=_"????"_______________________________| |
| - | 0076_4.1.4_U+002F_=_f8_80_80_80_af____=_"?????"_______________________________| |
| - | 0077_4.1.5_U+002F_=_fc_80_80_80_80_af_=_"??????"_______________________________| |
| + | 0073_4.1.1_U+002F_=_c0_af_____________=_"?"_______________________________| |
| + | 0074_4.1.2_U+002F_=_e0_80_af__________=_"?"_______________________________| |
| + | 0075_4.1.3_U+002F_=_f0_80_80_af_______=_"?"_______________________________| |
| + | 0076_4.1.4_U+002F_=_f8_80_80_80_af____=_"?"_______________________________| |
| + | 0077_4.1.5_U+002F_=_fc_80_80_80_80_af_=_"?"_______________________________| |
| 0078_4.2__Maximum_overlong_sequences______________________________________| | |
| - | 0079_4.2.1__U-0000007F_=_c1_bf_____________=_"??"__________________________| |
| + | 0079_4.2.1__U-0000007F_=_c1_bf_____________=_"?"__________________________| |
| 0080_4.2.2__U-000007FF_=_e0_9f_bf__________=_"?"__________________________| | |
| 0081_4.2.3__U-0000FFFF_=_f0_8f_bf_bf_______=_"?"__________________________| | |
| 0082_4.2.4__U-001FFFFF_=_f8_87_bf_bf_bf____=_"?"__________________________| | |
| 0083_4.2.5__U-03FFFFFF_=_fc_83_bf_bf_bf_bf_=_"?"__________________________| | |
| 0084_4.3__Overlong_representation_of_the_NUL_character____________________| | |
| - | 0085_4.3.1__U+0000_=_c0_80_____________=_"??"______________________________| |
| - | 0086_4.3.2__U+0000_=_e0_80_80__________=_"???"______________________________| |
| - | 0087_4.3.3__U+0000_=_f0_80_80_80_______=_"????"______________________________| |
| - | 0088_4.3.4__U+0000_=_f8_80_80_80_80____=_"?????"______________________________| |
| - | 0089_4.3.5__U+0000_=_fc_80_80_80_80_80_=_"??????"______________________________| |
| + | 0085_4.3.1__U+0000_=_c0_80_____________=_"?"______________________________| |
| + | 0086_4.3.2__U+0000_=_e0_80_80__________=_"?"______________________________| |
| + | 0087_4.3.3__U+0000_=_f0_80_80_80_______=_"?"______________________________| |
| + | 0088_4.3.4__U+0000_=_f8_80_80_80_80____=_"?"______________________________| |
| + | 0089_4.3.5__U+0000_=_fc_80_80_80_80_80_=_"?"______________________________| |
| 0090_5__Illegal_code_positions____________________________________________| | |
| 0091_5.1_Single_UTF-16_surrogates_________________________________________| | |
| 0092_5.1.1__U+D800_=_ed_a0_80_=_"?"_______________________________________| | |