diff --git a/localedata/Makefile b/localedata/Makefile index 94014370f5..4a23593cca 100644 --- a/localedata/Makefile +++ b/localedata/Makefile @@ -236,6 +236,7 @@ tests = \ bug-iconv-trans \ bug-setlocale1 \ bug-usesetlocale \ + tst-bz13988 \ tst-c-utf8-consistency \ tst-digits \ tst-iconv-emojis-trans \ diff --git a/localedata/tst-bz13988.c b/localedata/tst-bz13988.c new file mode 100644 index 0000000000..8d6f399bbc --- /dev/null +++ b/localedata/tst-bz13988.c @@ -0,0 +1,53 @@ +/* Localized test for BZ #13988. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <locale.h> +#include <stdio.h> +#include <string.h> + +#include <libc-diag.h> +#include <support/check.h> + +#define PD "\xd9\xab" + +static int +do_test (void) +{ + if (setlocale (LC_ALL, "fa_IR.UTF-8") == NULL) + FAIL_EXIT1 ("setlocale (LC_ALL, \"fa_IR.UTF-8\")"); + + char s[] = "+" PD "e"; + FILE *f = fmemopen (s, strlen (s), "r"); + + /* Avoid: "warning: 'I' flag used with '%f' gnu_scanf format [-Wformat=]"; + cf. GCC PR c/119514. */ + DIAG_PUSH_NEEDS_COMMENT; + DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat"); + + /* This should fail to parse a floating-point number, and leave 'e' in the + input. */ + double d; + TEST_VERIFY_EXIT (fscanf (f, "%Ilf", &d) == 0); + TEST_VERIFY_EXIT (fgetc (f) == 'e'); + + DIAG_POP_NEEDS_COMMENT; + + return 0; +} + +#include <support/test-driver.c> diff --git a/stdio-common/vfscanf-internal.c b/stdio-common/vfscanf-internal.c index 87f23b5845..6817fc1542 100644 --- a/stdio-common/vfscanf-internal.c +++ b/stdio-common/vfscanf-internal.c @@ -2409,7 +2409,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 +2426,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 +2464,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. */