]> diplodocus.org Git - nmh/commitdiff
sbr/fmt_scan.c: Only wcwidth(3) a valid mbtowc(3) result.
authorRalph Corderoy <ralph@inputplus.co.uk>
Tue, 25 Apr 2017 23:14:26 +0000 (00:14 +0100)
committerRalph Corderoy <ralph@inputplus.co.uk>
Wed, 26 Apr 2017 06:43:39 +0000 (07:43 +0100)
The assert(3) added by 80a9e99f7078199500d2d53c8d77d1b92af06fbc is
failing, but not reproducibly.  It's probable that mbtowc() is returning
a negative, and not altering wide_char, leaving it as random stack
content.  Taking its wcwidth() then sometimes also returns negative,
causing the assert() failure.  Initialising wide_char before the call
isn't a solution as it isn't documented if it's modified to an invalid
value on an error return.

Instead, delay calculating the wcwidth() until after the possible
substitution of "?".  Leave the assert() in place.

sbr/fmt_scan.c

index de1e080600b01e405660b488c4ec72df1aeab3f5..9377b393e4237199b50bbb8fc774427bce307a19 100644 (file)
@@ -256,16 +256,15 @@ cpstripped (charstring_t dest, size_t max, char *str)
     while (*str != '\0' && len > 0 && max > 0) {
 #ifdef MULTIBYTE_SUPPORT
        char_len = mbtowc(&wide_char, str, len);
     while (*str != '\0' && len > 0 && max > 0) {
 #ifdef MULTIBYTE_SUPPORT
        char_len = mbtowc(&wide_char, str, len);
-       w = wcwidth(wide_char);
 
        /*
         * If mbrtowc() failed, then we have a character that isn't valid
 
        /*
         * If mbrtowc() failed, then we have a character that isn't valid
-        * in the current encoding.  Replace it with a '?'.  We do that by
+        * in the current encoding, or len wasn't enough for the whole
+        * multi-byte rune to be read.  Replace it with a '?'.  We do that by
         * setting the alstr variable to the value of the replacement string;
         * altstr is used below when the bytes are copied into the output
         * buffer.
         */
         * setting the alstr variable to the value of the replacement string;
         * altstr is used below when the bytes are copied into the output
         * buffer.
         */
-
        if (char_len < 0) {
            altstr = "?";
            char_len = mbtowc(&wide_char, altstr, 1);
        if (char_len < 0) {
            altstr = "?";
            char_len = mbtowc(&wide_char, altstr, 1);
@@ -297,6 +296,7 @@ cpstripped (charstring_t dest, size_t max, char *str)
        prevCtrl = 0;
 
 #ifdef MULTIBYTE_SUPPORT
        prevCtrl = 0;
 
 #ifdef MULTIBYTE_SUPPORT
+       w = wcwidth(wide_char);
        assert(w >= 0);
        if (max >= (size_t) w) {
            charstring_push_back_chars (dest, altstr ? altstr : str, char_len, w);
        assert(w >= 0);
        if (max >= (size_t) w) {
            charstring_push_back_chars (dest, altstr ? altstr : str, char_len, w);