diff options
Diffstat (limited to 'stdio-common/vfscanf-internal.c')
-rw-r--r-- | stdio-common/vfscanf-internal.c | 62 |
1 files changed, 43 insertions, 19 deletions
diff --git a/stdio-common/vfscanf-internal.c b/stdio-common/vfscanf-internal.c index 87f23b5..b965c7b 100644 --- a/stdio-common/vfscanf-internal.c +++ b/stdio-common/vfscanf-internal.c @@ -1463,22 +1463,24 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, /* Look for a leading indication of base. */ if (width != 0 && c == L_('0')) { + WINT_T ctmp = c; + if (width > 0) --width; - - char_buffer_add (&charbuf, c); c = inchar (); - if (width != 0 && TOLOWER (c) == L_('x')) + if (width != 0 + && TOLOWER (c) == L_('x') + && (base == 0 || base == 16)) { - if (base == 0) - base = 16; - if (base == 16) - { - if (width > 0) - --width; - c = inchar (); - } + base = 16; + if (width > 0) + --width; + /* If we try to read a number in hexadecimal notation + and we have only the `0x' prefix, this is an error. */ + if (width == 0) + conv_error (); + c = inchar (); } else if (width != 0 && TOLOWER (c) == L_('b') @@ -1489,10 +1491,18 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, base = 2; if (width > 0) --width; + /* If we try to read a number in binary notation and + we have only the `0b' prefix, this is an error. */ + if (width == 0) + conv_error (); c = inchar (); } - else if (base == 0) - base = 8; + else + { + if (base == 0) + base = 8; + char_buffer_add (&charbuf, ctmp); + } } if (base == 0) @@ -2145,8 +2155,13 @@ digits_extended_fail: c = inchar (); if (width > 0) --width; - if (width != 0 && TOLOWER (c) == L_('x')) + if (TOLOWER (c) == L_('x')) { + /* If we try to read a number in hexadecimal notation + and we have only the `0x' prefix, this is an error. */ + if (width == 0) + conv_error (); + /* It is a number in hexadecimal format. */ char_buffer_add (&charbuf, c); @@ -2189,6 +2204,7 @@ digits_extended_fail: { char_buffer_add (&charbuf, exp_char); got_e = got_dot = 1; + got_digit = 0; } else { @@ -2409,7 +2425,7 @@ digits_extended_fail: if (got_e && charbuf.current[-1] == exp_char && (c == L_('-') || c == L_('+'))) char_buffer_add (&charbuf, c); - else if (char_buffer_size (&charbuf) > got_sign && !got_e + else if (got_digit && !got_e && (CHAR_T) TOLOWER (c) == exp_char) { char_buffer_add (&charbuf, exp_char); @@ -2426,7 +2442,10 @@ digits_extended_fail: if (c == wcdigits[n]) { if (n < 10) - char_buffer_add (&charbuf, L_('0') + n); + { + char_buffer_add (&charbuf, L_('0') + n); + got_digit = 1; + } else if (n == 11 && !got_dot) { char_buffer_add (&charbuf, decimal); @@ -2461,7 +2480,10 @@ digits_extended_fail: width = avail; if (n < 10) - char_buffer_add (&charbuf, L_('0') + n); + { + char_buffer_add (&charbuf, L_('0') + n); + got_digit = 1; + } else if (n == 11 && !got_dot) { /* Add all the characters. */ @@ -2532,11 +2554,13 @@ digits_extended_fail: /* Have we read any character? If we try to read a number in hexadecimal notation and we have read only the `0x' - prefix this is an error. */ + prefix this is an error. Also it is an error where we + have read no digits after the exponent character. */ if (__glibc_unlikely (char_buffer_size (&charbuf) == got_sign || ((flags & HEXA_FLOAT) && (char_buffer_size (&charbuf) - == 2 + got_sign)))) + == 2 + got_sign))) + || (got_e && !got_digit)) conv_error (); scan_float: |