diff options
| author | Avinal Kumar <avinal.xlvii@gmail.com> | 2024-10-25 15:48:27 +0530 |
|---|---|---|
| committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2024-10-25 15:05:06 -0300 |
| commit | 04e8698fcca7d1e932bc54f5b60e1bbce2e87601 (patch) | |
| tree | 43b2939f0ef8a5abf808806137cd1e30b7217a28 /stdio-common/vfscanf-internal.c | |
| parent | ac73067cb7a328bf106ecd041c020fc61be7e087 (diff) | |
| download | glibc-04e8698fcca7d1e932bc54f5b60e1bbce2e87601.tar.xz glibc-04e8698fcca7d1e932bc54f5b60e1bbce2e87601.zip | |
stdio-common: Fix scanf parsing for NaN types [BZ #30647]
The scanf family of functions like sscanf and fscanf currently
ignore nan() and nan(n-char-sequence). This happens because
__vfscanf_internal only checks for 'nan'.
This commit adds support for all valid nan types i.e. nan, nan()
and nan(n-char-sequence), where n-char-sequence can be
[a-zA-Z0-9_]+, thus fixing the bug 30647. Any other representation
of NaN should result in conversion error.
New tests are also added to verify the correct parsing of NaN types for
float, double and long double formats.
Signed-off-by: Avinal Kumar <avinal.xlvii@gmail.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'stdio-common/vfscanf-internal.c')
| -rw-r--r-- | stdio-common/vfscanf-internal.c | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/stdio-common/vfscanf-internal.c b/stdio-common/vfscanf-internal.c index 1b82deffa7..5f38f991cc 100644 --- a/stdio-common/vfscanf-internal.c +++ b/stdio-common/vfscanf-internal.c @@ -2028,7 +2028,51 @@ digits_extended_fail: if (width > 0) --width; char_buffer_add (&charbuf, c); - /* It is "nan". */ + /* It is at least "nan". Now we check for nan() and + nan(n-char-sequence). */ + if (width != 0 && inchar () != EOF) + { + if (c == L_('(')) + { + if (width > 0) + --width; + char_buffer_add (&charbuf, c); + /* A '(' was observed, check for a closing ')', there + may or may not be a n-char-sequence in between. We + have to check the longest prefix until there is a + conversion error or closing parenthesis. */ + do + { + if (__glibc_unlikely (width == 0 + || inchar () == EOF)) + { + /* Conversion error because we ran out of + characters. */ + conv_error (); + break; + } + if (!((c >= L_('0') && c <= L_('9')) + || (c >= L_('A') && c <= L_('Z')) + || (c >= L_('a') && c <= L_('z')) + || c == L_('_') || c == L_(')'))) + { + /* Invalid character was observed. Only valid + characters are [a-zA-Z0-9_] and ')'. */ + conv_error (); + break; + } + if (width > 0) + --width; + char_buffer_add (&charbuf, c); + } + while (c != L_(')')); + /* The loop only exits successfully when ')' is the + last character. */ + } + else + /* It is only 'nan'. */ + ungetc (c, s); + } goto scan_float; } else if (TOLOWER (c) == L_('i')) |
