1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-07 06:43:00 +03:00

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>
This commit is contained in:
Avinal Kumar
2024-10-25 15:48:27 +05:30
committed by Adhemerval Zanella
parent ac73067cb7
commit 04e8698fcc
3 changed files with 129 additions and 1 deletions

View File

@@ -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'))