Message ID | 54811be2-18d4-10ca-ec1f-d4b06aeb203f@redhat.com |
---|---|
State | New |
Headers | show |
Series | [v2] stdio-common: Add test for vfscanf with matches longer than INT_MAX [BZ #27650] | expand |
* Maciej W. Rozycki: > --- /dev/null > +++ glibc/stdio-common/tst-scanf-bz27650.c > @@ -0,0 +1,92 @@ > +/* Test for BZ #27650, formatted input matching beyond INT_MAX. I like how much shorter the test is now. > +#include <mcheck.h> Where is <mcheck.h> used? > + if (v == EOF || e != 0) > + error (EXIT_FAILURE, e ? errno : 0, > + "fscanf: input failure, at %u", written); Tests should not write diagnostics to standard error (where they get interspersed with make output). Please #include <support/check.h> and use FAIL_EXIT1 instead (or TEST_VERIFY, TEST_COMPARE …). > + if (!feof (in)) > + { > + v = fgetc (in); > + if (v == EOF) > + error (EXIT_FAILURE, errno, "fgetc: input failure"); > + else if (v == '\n') > + error (EXIT_FAILURE, 0, "unexpected new line character received"); > + else > + error (EXIT_FAILURE, 0, > + "character received after end of file expected: \\x%02x", v); > + } Missing fclose (in)?
On Tue, 2 Jul 2024, Florian Weimer wrote: > > +#include <mcheck.h> > > Where is <mcheck.h> used? There's a call to `mtrace' in `do_test' right at the beginning. > > + if (v == EOF || e != 0) > > + error (EXIT_FAILURE, e ? errno : 0, > > + "fscanf: input failure, at %u", written); > > Tests should not write diagnostics to standard error (where they get > interspersed with make output). Please #include <support/check.h> and > use FAIL_EXIT1 instead (or TEST_VERIFY, TEST_COMPARE …). There's prior usage, presumably with older test cases, but indeed I've become aware of this peculiarity in the course of my other effort, and it's just escaped me here. Honestly, given that there's no use for fd 2 for test cases the test driver could well just assign `stderr = stdio', making all the available standard error reporting facilities work as expected automagically. Maybe it's worth doing as a separate cleanup? Anyway the macros you refer to standardise the structure of the messages produced, so after some experimenting I chose to follow your suggestion rather than doing `stderr = stdio'. However sadly there is currently no macro that lets one pass a descriptive message but does not terminate the program or return from the current function. So I chose to trivially add one and converted the patch into a mini patch series, having concluded that calling `support_print_failure_impl' directly from a test case felt a bit hackish. > > + if (!feof (in)) > > + { > > + v = fgetc (in); > > + if (v == EOF) > > + error (EXIT_FAILURE, errno, "fgetc: input failure"); > > + else if (v == '\n') > > + error (EXIT_FAILURE, 0, "unexpected new line character received"); > > + else > > + error (EXIT_FAILURE, 0, > > + "character received after end of file expected: \\x%02x", v); > > + } > > Missing fclose (in)? Technically not needed, but you're right it's a bit sloppy not to have it. This however requires the test case to be reshaped a little for the cleanup to be always called provided that the stream has been successfully opened. I have posted v3 now. Maciej
On Thu, 4 Jul 2024, Maciej W. Rozycki wrote: > > > +#include <mcheck.h> > > > > Where is <mcheck.h> used? > > There's a call to `mtrace' in `do_test' right at the beginning. And I have spotted that for this to have any effect explicit arrangements have to be made for the test harness, so I have now posted v4 to address that, superseding v3. Sorry for the extra noise. Maciej
On Thu, 4 Jul 2024, Maciej W. Rozycki wrote: > And I have spotted that for this to have any effect explicit arrangements > have to be made for the test harness, so I have now posted v4 to address > that, superseding v3. Sorry for the extra noise. For the record, I have obviously noticed the CI failures, hard to miss. It just did not occur to me, sigh, that adding a FAIL definition to support/check.h is actually a global change and therefore requires running the whole test suite, unlike with earlier iterations. And it happened that the FAIL definition clashed with a bunch of same-named local macros, including, sadly, some recently added, which could have been chosen to use support/check.h facilities instead. I guess it wasn't my day yesterday. I've been working on v5 since I became aware of the problem. Current ETA is Monday next week. Maciej
Index: glibc/stdio-common/Makefile =================================================================== --- glibc.orig/stdio-common/Makefile +++ glibc/stdio-common/Makefile @@ -244,6 +244,7 @@ tests := \ tst-scanf-binary-c23 \ tst-scanf-binary-gnu11 \ tst-scanf-binary-gnu89 \ + tst-scanf-bz27650 \ tst-scanf-intn \ tst-scanf-round \ tst-scanf-to_inpunct \ @@ -314,6 +315,7 @@ generated += \ tst-printf-fp-free.mtrace \ tst-printf-fp-leak-mem.out \ tst-printf-fp-leak.mtrace \ + tst-scanf-bz27650.mtrace \ tst-vfprintf-width-prec-mem.out \ tst-vfprintf-width-prec.mtrace \ # generated Index: glibc/stdio-common/tst-scanf-bz27650.c =================================================================== --- /dev/null +++ glibc/stdio-common/tst-scanf-bz27650.c @@ -0,0 +1,92 @@ +/* Test for BZ #27650, formatted input matching beyond INT_MAX. + Copyright (C) 2024 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 <error.h> +#include <errno.h> +#include <limits.h> +#include <mcheck.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/types.h> + +#include <support/test-driver.h> + +/* Produce a stream of more than INT_MAX characters via buffer BUF of + size SIZE according to bookkeeping in COOKIE and then return EOF. */ + +static ssize_t +io_read (void *cookie, char *buf, size_t size) +{ + unsigned int *written = cookie; + unsigned int w = *written; + + if (w > INT_MAX) + return 0; + + memset (buf, 'a', size); + *written = w + size; + return size; +} + +/* Consume a stream of more than INT_MAX characters from an artificial + input stream of which none is the new line character. The call to + fscanf is supposed to complete upon the EOF condition of input, + however in the presence of BZ #27650 it will terminate prematurely + with characters still outstanding in input. Diagnose the condition + and return status accordingly. */ + +int +do_test (void) +{ + static cookie_io_functions_t io_funcs = { .read = io_read }; + unsigned int written = 0; + FILE *in; + int v, e; + + mtrace (); + + in = fopencookie (&written, "r", io_funcs); + if (in == NULL) + error (EXIT_FAILURE, errno, "fopencookie"); + + v = fscanf (in, "%*[^\n]"); + e = ferror (in); + if (v == EOF || e != 0) + error (EXIT_FAILURE, e ? errno : 0, + "fscanf: input failure, at %u", written); + + if (!feof (in)) + { + v = fgetc (in); + if (v == EOF) + error (EXIT_FAILURE, errno, "fgetc: input failure"); + else if (v == '\n') + error (EXIT_FAILURE, 0, "unexpected new line character received"); + else + error (EXIT_FAILURE, 0, + "character received after end of file expected: \\x%02x", v); + } + + return EXIT_SUCCESS; +} + +#define TIMEOUT (DEFAULT_TIMEOUT * 8) +#include <support/test-driver.c>