diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-12-27 19:31:37 +0000 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-12-27 19:31:37 +0000 |
commit | 74a412373b66a38b6ce8156f027ce26f89a7462f (patch) | |
tree | a59ce0af7ffd48641ca9124d697f7a6b57b26931 /stdio-common | |
parent | 2004eeba8fb2a92105bbf95b280fff6dc1d84144 (diff) | |
parent | 4cbfda396f7cd9e83116c28965ade73d80c1cb82 (diff) |
Merge commit 'refs/top-bases/t/ONSTACK' into t/ONSTACK
Diffstat (limited to 'stdio-common')
121 files changed, 2277 insertions, 797 deletions
diff --git a/stdio-common/Makefile b/stdio-common/Makefile index cc79d347bc..a10f12ab3c 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2016 Free Software Foundation, Inc. +# Copyright (C) 1991-2018 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 @@ -35,11 +35,11 @@ routines := \ perror psignal \ tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \ getline getw putw \ - remove rename renameat \ + remove rename renameat renameat2 \ flockfile ftrylockfile funlockfile \ isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \ isoc99_vsscanf \ - psiginfo + psiginfo gentempfd aux := errlist siglist printf-parsemb printf-parsewc fxprintf @@ -58,16 +58,23 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \ bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \ bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3 \ - tst-printf-bz18872 + tst-printf-bz18872 tst-vfprintf-width-prec tst-fmemopen4 \ + tst-vfprintf-user-type \ + tst-vfprintf-mbs-prec \ + tst-scanf-round \ + tst-renameat2 \ -test-srcs = tst-unbputc tst-printf +test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-unbputc.out $(objpfx)tst-printf.out \ $(objpfx)tst-printf-bz18872-mem.out \ - $(objpfx)tst-setvbuf1-cmp.out + $(objpfx)tst-setvbuf1-cmp.out \ + $(objpfx)tst-vfprintf-width-prec-mem.out \ + $(objpfx)tst-printfsz-islongdouble.out generated += tst-printf-bz18872.c tst-printf-bz18872.mtrace \ - tst-printf-bz18872-mem.out + tst-printf-bz18872-mem.out \ + tst-vfprintf-width-prec.mtrace tst-vfprintf-width-prec-mem.out endif include ../Rules @@ -83,16 +90,24 @@ $(objpfx)tst-grouping.out: $(gen-locales) $(objpfx)tst-sprintf.out: $(gen-locales) $(objpfx)tst-sscanf.out: $(gen-locales) $(objpfx)tst-swprintf.out: $(gen-locales) +$(objpfx)tst-vfprintf-mbs-prec.out: $(gen-locales) endif tst-printf-bz18872-ENV = MALLOC_TRACE=$(objpfx)tst-printf-bz18872.mtrace +tst-vfprintf-width-prec-ENV = \ + MALLOC_TRACE=$(objpfx)tst-vfprintf-width-prec.mtrace $(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc - $(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \ + $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' > $@; \ $(evaluate-test) $(objpfx)tst-printf.out: tst-printf.sh $(objpfx)tst-printf - $(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \ + $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' > $@; \ + $(evaluate-test) + +$(objpfx)tst-printfsz-islongdouble.out: \ + tst-printfsz-islongdouble.sh $(objpfx)tst-printfsz-islongdouble + $(SHELL) $^ '$(test-program-prefix)' $@; \ $(evaluate-test) # We generate this source because it requires a printf invocation with @@ -100,19 +115,19 @@ $(objpfx)tst-printf.out: tst-printf.sh $(objpfx)tst-printf $(objpfx)tst-printf-bz18872.c: tst-printf-bz18872.sh rm -f $@ && $(BASH) $^ > $@.new && mv $@.new $@ -$(objpfx)tst-printf-bz18872-mem.out: $(objpfx)tst-printf-bz18872.out - $(common-objpfx)malloc/mtrace $(objpfx)tst-printf-bz18872.mtrace > $@; \ +$(objpfx)tst-%-mem.out: $(objpfx)tst-%.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-$*.mtrace > $@; \ $(evaluate-test) -CFLAGS-vfprintf.c = -Wno-uninitialized -CFLAGS-vfwprintf.c = -Wno-uninitialized +CFLAGS-vfprintf.c += -Wno-uninitialized +CFLAGS-vfwprintf.c += -Wno-uninitialized -CFLAGS-tmpfile.c = -fexceptions -CFLAGS-tmpfile64.c = -fexceptions -CFLAGS-tempname.c = -fexceptions -CFLAGS-psignal.c = -fexceptions -CFLAGS-vprintf.c = -fexceptions -CFLAGS-cuserid.c = -fexceptions +CFLAGS-tmpfile.c += -fexceptions +CFLAGS-tmpfile64.c += -fexceptions +CFLAGS-tempname.c += -fexceptions +CFLAGS-psignal.c += -fexceptions +CFLAGS-vprintf.c += -fexceptions +CFLAGS-cuserid.c += -fexceptions CFLAGS-vfprintf.c += -fexceptions CFLAGS-fprintf.c += -fexceptions @@ -126,17 +141,27 @@ CFLAGS-isoc99_vfscanf.c += -fexceptions CFLAGS-isoc99_vscanf.c += -fexceptions CFLAGS-isoc99_fscanf.c += -fexceptions CFLAGS-isoc99_scanf.c += -fexceptions -CFLAGS-errlist.c = $(fno-unit-at-a-time) -CFLAGS-siglist.c = $(fno-unit-at-a-time) +CFLAGS-errlist.c += $(fno-unit-at-a-time) +CFLAGS-siglist.c += $(fno-unit-at-a-time) # The following is a hack since we must compile scanf1{5,7}.c without any # GNU extension. The latter are needed, though, when internal headers # are used. So made sure we see the installed headers first. -CFLAGS-scanf15.c = -I../libio -I../stdlib -I../wcsmbs -I../time -I../string \ +CFLAGS-scanf15.c += -I../libio -I../stdlib -I../wcsmbs -I../time -I../string \ -I../wctype -CFLAGS-scanf17.c = -I../libio -I../stdlib -I../wcsmbs -I../time -I../string \ +CFLAGS-scanf17.c += -I../libio -I../stdlib -I../wcsmbs -I../time -I../string \ -I../wctype +CFLAGS-bug3.c += -DOBJPFX=\"$(objpfx)\" +CFLAGS-bug4.c += -DOBJPFX=\"$(objpfx)\" +CFLAGS-bug5.c += -DOBJPFX=\"$(objpfx)\" +CFLAGS-test-fseek.c += -DOBJPFX=\"$(objpfx)\" +CFLAGS-test-popen.c += -DOBJPFX=\"$(objpfx)\" +CFLAGS-test_rdwr.c += -DOBJPFX=\"$(objpfx)\" + +# tst-gets.c tests a deprecated function. +CFLAGS-tst-gets.c += -Wno-deprecated-declarations + CPPFLAGS += $(libio-mtsafe) $(objpfx)tst-setvbuf1.out: /dev/null $(objpfx)tst-setvbuf1 @@ -148,3 +173,4 @@ $(objpfx)tst-setvbuf1-cmp.out: tst-setvbuf1.expect $(objpfx)tst-setvbuf1.out $(evaluate-test) $(objpfx)tst-printf-round: $(libm) +$(objpfx)tst-scanf-round: $(libm) diff --git a/stdio-common/Versions b/stdio-common/Versions index 06b96f678a..b8217578c8 100644 --- a/stdio-common/Versions +++ b/stdio-common/Versions @@ -57,8 +57,13 @@ libc { psiginfo; register_printf_modifier; register_printf_type; register_printf_specifier; } + GLIBC_2.28 { + renameat2; + } GLIBC_PRIVATE { # global variables _itoa_lower_digits; + # Used in libcrypt. + __snprintf; } } diff --git a/stdio-common/_i18n_number.h b/stdio-common/_i18n_number.h index 324297be71..40797715c8 100644 --- a/stdio-common/_i18n_number.h +++ b/stdio-common/_i18n_number.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2016 Free Software Foundation, Inc. +/* Copyright (C) 2000-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gnu.org>, 2000. @@ -19,6 +19,7 @@ #include <stdbool.h> #include <wchar.h> #include <wctype.h> +#include <scratch_buffer.h> #include "../locale/outdigits.h" #include "../locale/outdigitswc.h" @@ -65,17 +66,13 @@ _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) /* Copy existing string so that nothing gets overwritten. */ CHAR_T *src; - bool use_alloca = __libc_use_alloca ((rear_ptr - w) * sizeof (CHAR_T)); - if (__builtin_expect (use_alloca, true)) - src = (CHAR_T *) alloca ((rear_ptr - w) * sizeof (CHAR_T)); - else - { - src = (CHAR_T *) malloc ((rear_ptr - w) * sizeof (CHAR_T)); - if (src == NULL) - /* If we cannot allocate the memory don't rewrite the string. - It is better than nothing. */ - return w; - } + struct scratch_buffer buffer; + scratch_buffer_init (&buffer); + if (!scratch_buffer_set_array_size (&buffer, rear_ptr - w, sizeof (CHAR_T))) + /* If we cannot allocate the memory don't rewrite the string. + It is better than nothing. */ + return w; + src = buffer.data; CHAR_T *s = (CHAR_T *) __mempcpy (src, w, (rear_ptr - w) * sizeof (CHAR_T)); @@ -110,8 +107,6 @@ _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) } } - if (! use_alloca) - free (src); - + scratch_buffer_free (&buffer); return w; } diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c index b05c59b014..3749ee97e3 100644 --- a/stdio-common/_itoa.c +++ b/stdio-common/_itoa.c @@ -1,5 +1,5 @@ /* Internal function for converting integers to ASCII. - Copyright (C) 1994-2016 Free Software Foundation, Inc. + Copyright (C) 1994-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund <tege@matematik.su.se> and Ulrich Drepper <drepper@gnu.org>. diff --git a/stdio-common/_itowa.c b/stdio-common/_itowa.c index acbb870e97..531be71ab3 100644 --- a/stdio-common/_itowa.c +++ b/stdio-common/_itowa.c @@ -1,5 +1,5 @@ /* Internal function for converting integers to ASCII. - Copyright (C) 1994-2016 Free Software Foundation, Inc. + Copyright (C) 1994-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund <tege@matematik.su.se> and Ulrich Drepper <drepper@gnu.org>. diff --git a/stdio-common/_itowa.h b/stdio-common/_itowa.h index a5bf6d143d..b0c8f99c49 100644 --- a/stdio-common/_itowa.h +++ b/stdio-common/_itowa.h @@ -1,5 +1,5 @@ /* Internal function for converting integers to ASCII. - Copyright (C) 1994-2016 Free Software Foundation, Inc. + Copyright (C) 1994-2018 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 diff --git a/stdio-common/asprintf.c b/stdio-common/asprintf.c index 5500aa90ce..bff858e657 100644 --- a/stdio-common/asprintf.c +++ b/stdio-common/asprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/bits/printf-ldbl.h b/stdio-common/bits/printf-ldbl.h index aaa092158a..d61a68253e 100644 --- a/stdio-common/bits/printf-ldbl.h +++ b/stdio-common/bits/printf-ldbl.h @@ -1,5 +1,5 @@ /* -mlong-double-64 compatibility mode for <printf.h> functions. - Copyright (C) 2006-2016 Free Software Foundation, Inc. + Copyright (C) 2006-2018 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 diff --git a/stdio-common/bug-vfprintf-nargs.c b/stdio-common/bug-vfprintf-nargs.c index f3cfb4a23b..f06137968b 100644 --- a/stdio-common/bug-vfprintf-nargs.c +++ b/stdio-common/bug-vfprintf-nargs.c @@ -1,5 +1,5 @@ /* Test for vfprintf nargs allocation overflow (BZ #13656). - Copyright (C) 2012-2016 Free Software Foundation, Inc. + Copyright (C) 2012-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Kees Cook <keescook@chromium.org>, 2012. diff --git a/stdio-common/bug16.c b/stdio-common/bug16.c index 1112c39d05..91bc452826 100644 --- a/stdio-common/bug16.c +++ b/stdio-common/bug16.c @@ -1,3 +1,4 @@ +#include <array_length.h> #include <stdio.h> #include <string.h> @@ -19,7 +20,7 @@ do_test (void) char buf[100]; int ret = 0; - for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i) + for (size_t i = 0; i < array_length (tests); ++i) { snprintf (buf, sizeof (buf), "%.0LA", tests[i].val); diff --git a/stdio-common/bug21.c b/stdio-common/bug21.c index ca27272ba1..7a8c6a3542 100644 --- a/stdio-common/bug21.c +++ b/stdio-common/bug21.c @@ -1,5 +1,5 @@ #include <stdio.h> -#include <libc-internal.h> +#include <libc-diag.h> static int do_test (void) diff --git a/stdio-common/bug25.c b/stdio-common/bug25.c index 30c133974b..617f21ab71 100644 --- a/stdio-common/bug25.c +++ b/stdio-common/bug25.c @@ -1,5 +1,6 @@ #include <stdio.h> #include <string.h> +#include <stdlib.h> #include <unistd.h> static const char expected[] = "\ diff --git a/stdio-common/bug26.c b/stdio-common/bug26.c index 4994f9c616..6b31f28920 100644 --- a/stdio-common/bug26.c +++ b/stdio-common/bug26.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2013-2016 Free Software Foundation, Inc. +/* Copyright (C) 2013-2018 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 diff --git a/stdio-common/bug3.c b/stdio-common/bug3.c index 6b2ed6b8e0..62a6cab330 100644 --- a/stdio-common/bug3.c +++ b/stdio-common/bug3.c @@ -6,7 +6,7 @@ main (void) { FILE *f; int i; - const char filename[] = "/tmp/bug3.test"; + const char filename[] = OBJPFX "bug3.test"; f = fopen(filename, "w+"); for (i=0; i<9000; i++) diff --git a/stdio-common/bug4.c b/stdio-common/bug4.c index a0377862a5..cf7fe116eb 100644 --- a/stdio-common/bug4.c +++ b/stdio-common/bug4.c @@ -10,7 +10,7 @@ main (int argc, char *argv[]) FILE *f; int i; char buffer[31]; - const char filename[] = "/tmp/bug4.test"; + const char filename[] = OBJPFX "bug4.test"; while ((i = getopt (argc, argv, "rw")) != -1) switch (i) diff --git a/stdio-common/bug5.c b/stdio-common/bug5.c index f655845891..7bfe9b2b8d 100644 --- a/stdio-common/bug5.c +++ b/stdio-common/bug5.c @@ -14,8 +14,8 @@ main (void) { FILE *in; FILE *out; - static char inname[] = "/tmp/bug5.in"; - static char outname[] = "/tmp/bug5.out"; + static char inname[] = OBJPFX "bug5test.in"; + static char outname[] = OBJPFX "bug5test.out"; char *printbuf; size_t i; int result; diff --git a/stdio-common/bug7.c b/stdio-common/bug7.c index 2b1efe3bc6..c9c2ef5139 100644 --- a/stdio-common/bug7.c +++ b/stdio-common/bug7.c @@ -1,21 +1,25 @@ /* Regression test for fseek and freopen bugs. */ #include <stdio.h> +#include <stdlib.h> +#include <unistd.h> int main (int argc, char *argv[]) { int lose = 0; - char filename[L_tmpnam]; + char filename[] = "/tmp/bug7.XXXXXX"; FILE *fp; - if (tmpnam (filename) == NULL) + int fd = mkstemp (filename); + if (fd == -1) { - printf ("tmpnam failed\n"); + printf ("mkstemp failed\n"); lose = 1; } else { + close (fd); fp = fopen (filename, "w+"); fprintf (fp, "Hello world!\n"); fflush (fp); @@ -32,17 +36,21 @@ main (int argc, char *argv[]) { FILE *file1; FILE *file2; - char filename1[L_tmpnam]; - char filename2[L_tmpnam]; + char filename1[] = "/tmp/bug7.XXXXXX"; + char filename2[] = "/tmp/bug7.XXXXXX"; int ch; - if (tmpnam (filename1) == NULL || tmpnam (filename2) == NULL) + int fd1 = mkstemp (filename1); + int fd2 = mkstemp (filename2); + if (fd1 == -1 || fd2 == -1) { - printf ("tmpnam failed\n"); + printf ("mkstemp failed\n"); lose = 1; } else { + close (fd1); + close (fd2); file1 = fopen (filename1, "w"); fclose (file1); diff --git a/stdio-common/ctermid.c b/stdio-common/ctermid.c index d1577897d7..f4af8e98e9 100644 --- a/stdio-common/ctermid.c +++ b/stdio-common/ctermid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/cuserid.c b/stdio-common/cuserid.c index 574b46478f..bfae5bc038 100644 --- a/stdio-common/cuserid.c +++ b/stdio-common/cuserid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/dprintf.c b/stdio-common/dprintf.c index e9762e2230..11bd12b838 100644 --- a/stdio-common/dprintf.c +++ b/stdio-common/dprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/errlist.c b/stdio-common/errlist.c index 440a8e1920..b94b4b4422 100644 --- a/stdio-common/errlist.c +++ b/stdio-common/errlist.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -15,9 +15,9 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <array_length.h> #include <stddef.h> - const char *const _sys_errlist[] = { "Error 0", /* 0 */ @@ -33,4 +33,4 @@ const char *const _sys_errlist[] = "Too many open files", /* 10 = EMFILE */ }; -const int _sys_nerr = sizeof (_sys_errlist) / sizeof (_sys_errlist[0]); +const int _sys_nerr = array_length (_sys_errlist); diff --git a/stdio-common/errnobug.c b/stdio-common/errnobug.c index e046222875..7127c126fb 100644 --- a/stdio-common/errnobug.c +++ b/stdio-common/errnobug.c @@ -1,6 +1,6 @@ /* Regression test for reported old bug that errno is clobbered by the first successful output to a stream on an unseekable object. - Copyright (C) 1995-2016 Free Software Foundation, Inc. + Copyright (C) 1995-2018 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 diff --git a/stdio-common/flockfile.c b/stdio-common/flockfile.c index 34c59d738e..60ddd34087 100644 --- a/stdio-common/flockfile.c +++ b/stdio-common/flockfile.c @@ -1,5 +1,5 @@ /* Lock I/O stream. Singlethreaded version. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 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 diff --git a/stdio-common/fprintf.c b/stdio-common/fprintf.c index 1c41b0f5a4..2bbf14bf5d 100644 --- a/stdio-common/fprintf.c +++ b/stdio-common/fprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/fscanf.c b/stdio-common/fscanf.c index 4c10444a0a..b60a2a3b81 100644 --- a/stdio-common/fscanf.c +++ b/stdio-common/fscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/ftrylockfile.c b/stdio-common/ftrylockfile.c index fe871e1c5e..02e426b6f1 100644 --- a/stdio-common/ftrylockfile.c +++ b/stdio-common/ftrylockfile.c @@ -1,5 +1,5 @@ /* Try locking I/O stream. Singlethreaded version. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 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 diff --git a/stdio-common/funlockfile.c b/stdio-common/funlockfile.c index 95fb06850b..a59a18c9a4 100644 --- a/stdio-common/funlockfile.c +++ b/stdio-common/funlockfile.c @@ -1,5 +1,5 @@ /* Unlock I/O stream. Singlethreaded version. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 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 diff --git a/stdio-common/fxprintf.c b/stdio-common/fxprintf.c index 097265167d..c4a1146b20 100644 --- a/stdio-common/fxprintf.c +++ b/stdio-common/fxprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005-2016 Free Software Foundation, Inc. +/* Copyright (C) 2005-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gnu.org>. @@ -16,14 +16,50 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <assert.h> -#include <ctype.h> #include <stdarg.h> #include <stdio.h> -#include <wchar.h> +#include <stdlib.h> #include <string.h> +#include <wchar.h> #include <libioP.h> +static int +locked_vfxprintf (FILE *fp, const char *fmt, va_list ap) +{ + if (_IO_fwide (fp, 0) <= 0) + return _IO_vfprintf (fp, fmt, ap); + + /* We must convert the narrow format string to a wide one. + Each byte can produce at most one wide character. */ + wchar_t *wfmt; + mbstate_t mbstate; + int res; + int used_malloc = 0; + size_t len = strlen (fmt) + 1; + + if (__glibc_unlikely (len > SIZE_MAX / sizeof (wchar_t))) + { + __set_errno (EOVERFLOW); + return -1; + } + if (__libc_use_alloca (len * sizeof (wchar_t))) + wfmt = alloca (len * sizeof (wchar_t)); + else if ((wfmt = malloc (len * sizeof (wchar_t))) == NULL) + return -1; + else + used_malloc = 1; + + memset (&mbstate, 0, sizeof mbstate); + res = __mbsrtowcs (wfmt, &fmt, len, &mbstate); + + if (res != -1) + res = _IO_vfwprintf (fp, wfmt, ap); + + if (used_malloc) + free (wfmt); + + return res; +} int __fxprintf (FILE *fp, const char *fmt, ...) @@ -33,23 +69,31 @@ __fxprintf (FILE *fp, const char *fmt, ...) va_list ap; va_start (ap, fmt); + _IO_flockfile (fp); - int res; - if (_IO_fwide (fp, 0) > 0) - { - size_t len = strlen (fmt) + 1; - wchar_t wfmt[len]; - for (size_t i = 0; i < len; ++i) - { - assert (isascii (fmt[i])); - wfmt[i] = fmt[i]; - } - res = __vfwprintf (fp, wfmt, ap); - } - else - res = _IO_vfprintf (fp, fmt, ap); + int res = locked_vfxprintf (fp, fmt, ap); + _IO_funlockfile (fp); va_end (ap); + return res; +} +int +__fxprintf_nocancel (FILE *fp, const char *fmt, ...) +{ + if (fp == NULL) + fp = stderr; + + va_list ap; + va_start (ap, fmt); + _IO_flockfile (fp); + int save_flags2 = fp->_flags2; + fp->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + int res = locked_vfxprintf (fp, fmt, ap); + + fp->_flags2 = save_flags2; + _IO_funlockfile (fp); + va_end (ap); return res; } diff --git a/stdio-common/gentempfd.c b/stdio-common/gentempfd.c new file mode 100644 index 0000000000..d45cbb8588 --- /dev/null +++ b/stdio-common/gentempfd.c @@ -0,0 +1,26 @@ +/* Generate a temporary file descriptor. Generic/POSIX version. + Copyright (C) 2017-2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> + +int +__gen_tempfd (int flags) +{ + return -1; +} +libc_hidden_def (__gen_tempfd) diff --git a/stdio-common/getline.c b/stdio-common/getline.c index 39e4a39910..77f77c2400 100644 --- a/stdio-common/getline.c +++ b/stdio-common/getline.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -17,19 +17,15 @@ #include <stddef.h> #include <stdio.h> +#include "../libio/libioP.h" #undef __getline -#include "../libio/libioP.h" -#undef ssize_t -#define ssize_t _IO_ssize_t -#define __getdelim _IO_getdelim - /* Like getdelim, but always looks for a newline. */ ssize_t __getline (char **lineptr, size_t *n, FILE *stream) { - return __getdelim (lineptr, n, '\n', stream); + return _IO_getdelim (lineptr, n, '\n', stream); } weak_alias (__getline, getline) diff --git a/stdio-common/getw.c b/stdio-common/getw.c index abf5459e6f..781a0dc97b 100644 --- a/stdio-common/getw.c +++ b/stdio-common/getw.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/isoc99_fscanf.c b/stdio-common/isoc99_fscanf.c index 6fe490a69d..9cdf85e679 100644 --- a/stdio-common/isoc99_fscanf.c +++ b/stdio-common/isoc99_fscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/isoc99_scanf.c b/stdio-common/isoc99_scanf.c index 51f6c3c1a1..bf7dbe86bb 100644 --- a/stdio-common/isoc99_scanf.c +++ b/stdio-common/isoc99_scanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/isoc99_sscanf.c b/stdio-common/isoc99_sscanf.c index 57207dfcf4..56a60a2c05 100644 --- a/stdio-common/isoc99_sscanf.c +++ b/stdio-common/isoc99_sscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/isoc99_vfscanf.c b/stdio-common/isoc99_vfscanf.c index d4dc4360dd..b80e05f8db 100644 --- a/stdio-common/isoc99_vfscanf.c +++ b/stdio-common/isoc99_vfscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -21,7 +21,7 @@ /* Read formatted input from STREAM according to the format string FORMAT. */ /* VARARGS2 */ int -__isoc99_vfscanf (FILE *stream, const char *format, _IO_va_list args) +__isoc99_vfscanf (FILE *stream, const char *format, va_list args) { int done; diff --git a/stdio-common/isoc99_vscanf.c b/stdio-common/isoc99_vscanf.c index 2df433cbef..0b747f85ba 100644 --- a/stdio-common/isoc99_vscanf.c +++ b/stdio-common/isoc99_vscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -21,7 +21,7 @@ /* Read formatted input from STDIN according to the format string FORMAT. */ /* VARARGS2 */ int -__isoc99_vscanf (const char *format, _IO_va_list args) +__isoc99_vscanf (const char *format, va_list args) { int done; diff --git a/stdio-common/isoc99_vsscanf.c b/stdio-common/isoc99_vsscanf.c index 720f122083..ac85ef2d0d 100644 --- a/stdio-common/isoc99_vsscanf.c +++ b/stdio-common/isoc99_vsscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-2016 Free Software Foundation, Inc. +/* Copyright (C) 1993-2018 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 @@ -29,7 +29,7 @@ #include "../libio/strfile.h" int -__isoc99_vsscanf (const char *string, const char *format, _IO_va_list args) +__isoc99_vsscanf (const char *string, const char *format, va_list args) { int ret; _IO_strfile sf; diff --git a/stdio-common/itoa-digits.c b/stdio-common/itoa-digits.c index b819abc0ac..00619521ed 100644 --- a/stdio-common/itoa-digits.c +++ b/stdio-common/itoa-digits.c @@ -1,5 +1,5 @@ /* Digits. - Copyright (C) 1994-2016 Free Software Foundation, Inc. + Copyright (C) 1994-2018 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 diff --git a/stdio-common/itoa-udigits.c b/stdio-common/itoa-udigits.c index ac303ca5a2..607b08ee3b 100644 --- a/stdio-common/itoa-udigits.c +++ b/stdio-common/itoa-udigits.c @@ -1,5 +1,5 @@ /* Digits. - Copyright (C) 1994-2016 Free Software Foundation, Inc. + Copyright (C) 1994-2018 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 diff --git a/stdio-common/itowa-digits.c b/stdio-common/itowa-digits.c index 399d57e981..5727a4ec88 100644 --- a/stdio-common/itowa-digits.c +++ b/stdio-common/itowa-digits.c @@ -1,5 +1,5 @@ /* Digits. - Copyright (C) 1994-2016 Free Software Foundation, Inc. + Copyright (C) 1994-2018 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 diff --git a/stdio-common/perror.c b/stdio-common/perror.c index c2bba6800e..b6836c93f6 100644 --- a/stdio-common/perror.c +++ b/stdio-common/perror.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h index 0f21fedc3d..e07186ec83 100644 --- a/stdio-common/printf-parse.h +++ b/stdio-common/printf-parse.h @@ -1,5 +1,5 @@ /* Internal header for parsing printf format strings. - Copyright (C) 1995-2016 Free Software Foundation, Inc. + Copyright (C) 1995-2018 Free Software Foundation, Inc. This file is part of th GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/stdio-common/printf-parsemb.c b/stdio-common/printf-parsemb.c index 66cef10b20..ecbc4e3169 100644 --- a/stdio-common/printf-parsemb.c +++ b/stdio-common/printf-parsemb.c @@ -1,5 +1,5 @@ /* Helper functions for parsing printf format strings. - Copyright (C) 1995-2016 Free Software Foundation, Inc. + Copyright (C) 1995-2018 Free Software Foundation, Inc. This file is part of th GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -79,6 +79,7 @@ __parse_one_specmb (const UCHAR_T *format, size_t posn, spec->info.extra = 0; spec->info.pad = ' '; spec->info.wide = sizeof (UCHAR_T) > 1; + spec->info.is_binary128 = 0; /* Test for positional argument. */ if (ISDIGIT (*format)) diff --git a/stdio-common/printf-prs.c b/stdio-common/printf-prs.c index b51b567f10..93b872a875 100644 --- a/stdio-common/printf-prs.c +++ b/stdio-common/printf-prs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/printf.c b/stdio-common/printf.c index acc67d2740..205b5e42df 100644 --- a/stdio-common/printf.c +++ b/stdio-common/printf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/printf.h b/stdio-common/printf.h index d731216197..06d674359a 100644 --- a/stdio-common/printf.h +++ b/stdio-common/printf.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -22,11 +22,12 @@ __BEGIN_DECLS -#define __need_FILE -#include <stdio.h> +#include <bits/types/FILE.h> + #define __need_size_t #define __need_wchar_t #include <stddef.h> + #include <stdarg.h> @@ -47,7 +48,9 @@ struct printf_info unsigned int is_char:1; /* hh flag. */ unsigned int wide:1; /* Nonzero for wide character streams. */ unsigned int i18n:1; /* I flag. */ - unsigned int __pad:4; /* Unused so far. */ + unsigned int is_binary128:1; /* Floating-point argument is ABI-compatible + with IEC 60559 binary128. */ + unsigned int __pad:3; /* Unused so far. */ unsigned short int user; /* Bits for user-installed modifiers. */ wchar_t pad; /* Padding character. */ }; @@ -111,13 +114,13 @@ extern int register_printf_function (int __spec, printf_function __func, it returns a positive value representing the bit set in the USER field in 'struct printf_info'. */ -extern int register_printf_modifier (const wchar_t *__str) __wur __THROW; +extern int register_printf_modifier (const wchar_t *__str) __THROW __wur; /* Register variable argument handler for user type. The return value is to be used in ARGINFO functions to signal the use of the type. */ -extern int register_printf_type (printf_va_arg_function __fct) __wur __THROW; +extern int register_printf_type (printf_va_arg_function __fct) __THROW __wur; /* Parse FMT, and fill in N elements of ARGTYPES with the diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c index 4134f8ab89..66ab59bad2 100644 --- a/stdio-common/printf_fp.c +++ b/stdio-common/printf_fp.c @@ -1,5 +1,5 @@ /* Floating point output for `printf'. - Copyright (C) 1995-2016 Free Software Foundation, Inc. + Copyright (C) 1995-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. @@ -21,6 +21,7 @@ /* The gmp headers need some configuration frobs. */ #define HAVE_ALLOCA 1 +#include <array_length.h> #include <libioP.h> #include <alloca.h> #include <ctype.h> @@ -55,17 +56,12 @@ #endif #include <assert.h> -/* This defines make it possible to use the same code for GNU C library and - the GNU I/O library. */ #define PUT(f, s, n) _IO_sputn (f, s, n) #define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n)) -/* We use this file GNU C library and GNU I/O library. So make - names equal. */ #undef putc #define putc(c, f) (wide \ ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f)) -#define size_t _IO_size_t -#define FILE _IO_FILE + /* Macros for doing the actual output. */ @@ -139,14 +135,11 @@ extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size, extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size, int *expt, int *is_neg, long double value); -extern unsigned int __guess_grouping (unsigned int intdig_max, - const char *grouping); static wchar_t *group_number (wchar_t *buf, wchar_t *bufend, unsigned int intdig_no, const char *grouping, - wchar_t thousands_sep, int ngroups) - internal_function; + wchar_t thousands_sep, int ngroups); struct hack_digit_param { @@ -209,15 +202,18 @@ hack_digit (struct hack_digit_param *p) } int -___printf_fp (FILE *fp, - const struct printf_info *info, - const void *const *args) +__printf_fp_l (FILE *fp, locale_t loc, + const struct printf_info *info, + const void *const *args) { /* The floating-point value to output. */ union { double dbl; - __long_double_t ldbl; + long double ldbl; +#if __HAVE_DISTINCT_FLOAT128 + _Float128 f128; +#endif } fpnum; @@ -234,9 +230,17 @@ ___printf_fp (FILE *fp, const char *special = NULL; const wchar_t *wspecial = NULL; + /* When _Float128 is enabled in the library and ABI-distinct from long + double, we need mp_limbs enough for any of them. */ +#if __HAVE_DISTINCT_FLOAT128 +# define GREATER_MANT_DIG FLT128_MANT_DIG +#else +# define GREATER_MANT_DIG LDBL_MANT_DIG +#endif /* We need just a few limbs for the input before shifting to the right position. */ - mp_limb_t fp_input[(LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB]; + mp_limb_t fp_input[(GREATER_MANT_DIG + BITS_PER_MP_LIMB - 1) + / BITS_PER_MP_LIMB]; /* We need to shift the contents of fp_input by this amount of bits. */ int to_shift = 0; @@ -263,18 +267,19 @@ ___printf_fp (FILE *fp, /* Figure out the decimal point character. */ if (info->extra == 0) { - decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); - decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); + decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT); + decimalwc = _nl_lookup_word + (loc, LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); } else { - decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT); + decimal = _nl_lookup (loc, LC_MONETARY, MON_DECIMAL_POINT); if (*decimal == '\0') - decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); - decimalwc = _NL_CURRENT_WORD (LC_MONETARY, + decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT); + decimalwc = _nl_lookup_word (loc, LC_MONETARY, _NL_MONETARY_DECIMAL_POINT_WC); if (decimalwc == L'\0') - decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, + decimalwc = _nl_lookup_word (loc, LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); } /* The decimal point character must not be zero. */ @@ -284,9 +289,9 @@ ___printf_fp (FILE *fp, if (info->group) { if (info->extra == 0) - grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); + grouping = _nl_lookup (loc, LC_NUMERIC, GROUPING); else - grouping = _NL_CURRENT (LC_MONETARY, MON_GROUPING); + grouping = _nl_lookup (loc, LC_MONETARY, MON_GROUPING); if (*grouping <= 0 || *grouping == CHAR_MAX) grouping = NULL; @@ -296,19 +301,20 @@ ___printf_fp (FILE *fp, if (wide) { if (info->extra == 0) - thousands_sepwc = - _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); + thousands_sepwc = _nl_lookup_word + (loc, LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); else thousands_sepwc = - _NL_CURRENT_WORD (LC_MONETARY, + _nl_lookup_word (loc, LC_MONETARY, _NL_MONETARY_THOUSANDS_SEP_WC); } else { if (info->extra == 0) - thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); + thousands_sep = _nl_lookup (loc, LC_NUMERIC, THOUSANDS_SEP); else - thousands_sep = _NL_CURRENT (LC_MONETARY, MON_THOUSANDS_SEP); + thousands_sep = _nl_lookup + (loc, LC_MONETARY, MON_THOUSANDS_SEP); } if ((wide && thousands_sepwc == L'\0') @@ -325,94 +331,62 @@ ___printf_fp (FILE *fp, else grouping = NULL; +#define PRINTF_FP_FETCH(FLOAT, VAR, SUFFIX, MANT_DIG) \ + { \ + (VAR) = *(const FLOAT *) args[0]; \ + \ + /* Check for special values: not a number or infinity. */ \ + if (isnan (VAR)) \ + { \ + is_neg = signbit (VAR); \ + if (isupper (info->spec)) \ + { \ + special = "NAN"; \ + wspecial = L"NAN"; \ + } \ + else \ + { \ + special = "nan"; \ + wspecial = L"nan"; \ + } \ + } \ + else if (isinf (VAR)) \ + { \ + is_neg = signbit (VAR); \ + if (isupper (info->spec)) \ + { \ + special = "INF"; \ + wspecial = L"INF"; \ + } \ + else \ + { \ + special = "inf"; \ + wspecial = L"inf"; \ + } \ + } \ + else \ + { \ + p.fracsize = __mpn_extract_##SUFFIX \ + (fp_input, array_length (fp_input), \ + &p.exponent, &is_neg, VAR); \ + to_shift = 1 + p.fracsize * BITS_PER_MP_LIMB - MANT_DIG; \ + } \ + } + /* Fetch the argument value. */ +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + PRINTF_FP_FETCH (_Float128, fpnum.f128, float128, FLT128_MANT_DIG) + else +#endif #ifndef __NO_LONG_DOUBLE_MATH if (info->is_long_double && sizeof (long double) > sizeof (double)) - { - fpnum.ldbl = *(const long double *) args[0]; - - /* Check for special values: not a number or infinity. */ - if (isnan (fpnum.ldbl)) - { - is_neg = signbit (fpnum.ldbl); - if (isupper (info->spec)) - { - special = "NAN"; - wspecial = L"NAN"; - } - else - { - special = "nan"; - wspecial = L"nan"; - } - } - else if (isinf (fpnum.ldbl)) - { - is_neg = signbit (fpnum.ldbl); - if (isupper (info->spec)) - { - special = "INF"; - wspecial = L"INF"; - } - else - { - special = "inf"; - wspecial = L"inf"; - } - } - else - { - p.fracsize = __mpn_extract_long_double (fp_input, - (sizeof (fp_input) / - sizeof (fp_input[0])), - &p.exponent, &is_neg, - fpnum.ldbl); - to_shift = 1 + p.fracsize * BITS_PER_MP_LIMB - LDBL_MANT_DIG; - } - } + PRINTF_FP_FETCH (long double, fpnum.ldbl, long_double, LDBL_MANT_DIG) else -#endif /* no long double */ - { - fpnum.dbl = *(const double *) args[0]; +#endif + PRINTF_FP_FETCH (double, fpnum.dbl, double, DBL_MANT_DIG) - /* Check for special values: not a number or infinity. */ - if (isnan (fpnum.dbl)) - { - is_neg = signbit (fpnum.dbl); - if (isupper (info->spec)) - { - special = "NAN"; - wspecial = L"NAN"; - } - else - { - special = "nan"; - wspecial = L"nan"; - } - } - else if (isinf (fpnum.dbl)) - { - is_neg = signbit (fpnum.dbl); - if (isupper (info->spec)) - { - special = "INF"; - wspecial = L"INF"; - } - else - { - special = "inf"; - wspecial = L"inf"; - } - } - else - { - p.fracsize = __mpn_extract_double (fp_input, - (sizeof (fp_input) - / sizeof (fp_input[0])), - &p.exponent, &is_neg, fpnum.dbl); - to_shift = 1 + p.fracsize * BITS_PER_MP_LIMB - DBL_MANT_DIG; - } - } +#undef PRINTF_FP_FETCH if (special) { @@ -448,7 +422,8 @@ ___printf_fp (FILE *fp, { mp_size_t bignum_size = ((abs (p.exponent) + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB - + (LDBL_MANT_DIG / BITS_PER_MP_LIMB > 2 ? 8 : 4)) + + (GREATER_MANT_DIG / BITS_PER_MP_LIMB > 2 + ? 8 : 4)) * sizeof (mp_limb_t); p.frac = (mp_limb_t *) alloca (bignum_size); p.tmp = (mp_limb_t *) alloca (bignum_size); @@ -463,7 +438,15 @@ ___printf_fp (FILE *fp, { /* |FP| >= 8.0. */ int scaleexpo = 0; - int explog = LDBL_MAX_10_EXP_LOG; + int explog; +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + explog = FLT128_MAX_10_EXP_LOG; + else + explog = LDBL_MAX_10_EXP_LOG; +#else + explog = LDBL_MAX_10_EXP_LOG; +#endif int exp10 = 0; const struct mp_power *powers = &_fpioconst_pow10[explog + 1]; int cnt_h, cnt_l, i; @@ -497,6 +480,27 @@ ___printf_fp (FILE *fp, { if (p.scalesize == 0) { +#if __HAVE_DISTINCT_FLOAT128 + if ((FLT128_MANT_DIG + > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB) + && info->is_binary128) + { +#define _FLT128_FPIO_CONST_SHIFT \ + (((FLT128_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) \ + - _FPIO_CONST_OFFSET) + /* 64bit const offset is not enough for + IEEE 854 quad long double (_Float128). */ + p.tmpsize = powers->arraysize + _FLT128_FPIO_CONST_SHIFT; + memcpy (p.tmp + _FLT128_FPIO_CONST_SHIFT, + &__tens[powers->arrayoff], + p.tmpsize * sizeof (mp_limb_t)); + MPN_ZERO (p.tmp, _FLT128_FPIO_CONST_SHIFT); + /* Adjust p.exponent, as scaleexpo will be this much + bigger too. */ + p.exponent += _FLT128_FPIO_CONST_SHIFT * BITS_PER_MP_LIMB; + } + else +#endif /* __HAVE_DISTINCT_FLOAT128 */ #ifndef __NO_LONG_DOUBLE_MATH if (LDBL_MANT_DIG > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB && info->is_long_double) @@ -637,7 +641,15 @@ ___printf_fp (FILE *fp, { /* |FP| < 1.0. */ int exp10 = 0; - int explog = LDBL_MAX_10_EXP_LOG; + int explog; +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + explog = FLT128_MAX_10_EXP_LOG; + else + explog = LDBL_MAX_10_EXP_LOG; +#else + explog = LDBL_MAX_10_EXP_LOG; +#endif const struct mp_power *powers = &_fpioconst_pow10[explog + 1]; /* Now shift the input value to its right place. */ @@ -1171,9 +1183,11 @@ ___printf_fp (FILE *fp, size_t decimal_len; size_t thousands_sep_len; wchar_t *copywc; - size_t factor = (info->i18n - ? _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) - : 1); + size_t factor; + if (info->i18n) + factor = _nl_lookup_word (loc, LC_CTYPE, _NL_CTYPE_MB_CUR_MAX); + else + factor = 1; decimal_len = strlen (decimal); @@ -1244,8 +1258,17 @@ ___printf_fp (FILE *fp, } return done; } +libc_hidden_def (__printf_fp_l) + +int +___printf_fp (FILE *fp, const struct printf_info *info, + const void *const *args) +{ + return __printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args); +} ldbl_hidden_def (___printf_fp, __printf_fp) ldbl_strong_alias (___printf_fp, __printf_fp) + /* Return the number of extra grouping characters that will be inserted into a number with INTDIG_MAX integer digits. */ @@ -1290,7 +1313,6 @@ __guess_grouping (unsigned int intdig_max, const char *grouping) Return the new end of buffer. */ static wchar_t * -internal_function group_number (wchar_t *buf, wchar_t *bufend, unsigned int intdig_no, const char *grouping, wchar_t thousands_sep, int ngroups) { diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c index 255c7e0372..df3956316d 100644 --- a/stdio-common/printf_fphex.c +++ b/stdio-common/printf_fphex.c @@ -1,5 +1,5 @@ /* Print floating point number in hexadecimal notation according to ISO C99. - Copyright (C) 1997-2016 Free Software Foundation, Inc. + Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -17,6 +17,7 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <array_length.h> #include <ctype.h> #include <ieee754.h> #include <math.h> @@ -31,21 +32,24 @@ #include <stdbool.h> #include <rounding-mode.h> +#if __HAVE_DISTINCT_FLOAT128 +# include "ieee754_float128.h" +# include <ldbl-128/printf_fphex_macros.h> +# define PRINT_FPHEX_FLOAT128 \ + PRINT_FPHEX (_Float128, fpnum.flt128, ieee854_float128, \ + IEEE854_FLOAT128_BIAS) +#endif + /* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */ #include <assert.h> -/* This defines make it possible to use the same code for GNU C library and - the GNU I/O library. */ #include <libioP.h> #define PUT(f, s, n) _IO_sputn (f, s, n) #define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n)) -/* We use this file GNU C library and GNU I/O library. So make - names equal. */ #undef putc #define putc(c, f) (wide \ ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f)) -#define size_t _IO_size_t -#define FILE _IO_FILE + /* Macros for doing the actual output. */ @@ -94,6 +98,9 @@ __printf_fphex (FILE *fp, { union ieee754_double dbl; long double ldbl; +#if __HAVE_DISTINCT_FLOAT128 + _Float128 flt128; +#endif } fpnum; @@ -157,82 +164,57 @@ __printf_fphex (FILE *fp, /* The decimal point character must never be zero. */ assert (*decimal != '\0' && decimalwc != L'\0'); +#define PRINTF_FPHEX_FETCH(FLOAT, VAR) \ + { \ + (VAR) = *(const FLOAT *) args[0]; \ + \ + /* Check for special values: not a number or infinity. */ \ + if (isnan (VAR)) \ + { \ + if (isupper (info->spec)) \ + { \ + special = "NAN"; \ + wspecial = L"NAN"; \ + } \ + else \ + { \ + special = "nan"; \ + wspecial = L"nan"; \ + } \ + } \ + else \ + { \ + if (isinf (VAR)) \ + { \ + if (isupper (info->spec)) \ + { \ + special = "INF"; \ + wspecial = L"INF"; \ + } \ + else \ + { \ + special = "inf"; \ + wspecial = L"inf"; \ + } \ + } \ + } \ + negative = signbit (VAR); \ + } /* Fetch the argument value. */ +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + PRINTF_FPHEX_FETCH (_Float128, fpnum.flt128) + else +#endif #ifndef __NO_LONG_DOUBLE_MATH if (info->is_long_double && sizeof (long double) > sizeof (double)) - { - fpnum.ldbl = *(const long double *) args[0]; - - /* Check for special values: not a number or infinity. */ - if (isnan (fpnum.ldbl)) - { - if (isupper (info->spec)) - { - special = "NAN"; - wspecial = L"NAN"; - } - else - { - special = "nan"; - wspecial = L"nan"; - } - } - else - { - if (isinf (fpnum.ldbl)) - { - if (isupper (info->spec)) - { - special = "INF"; - wspecial = L"INF"; - } - else - { - special = "inf"; - wspecial = L"inf"; - } - } - } - negative = signbit (fpnum.ldbl); - } + PRINTF_FPHEX_FETCH (long double, fpnum.ldbl) else -#endif /* no long double */ - { - fpnum.dbl.d = *(const double *) args[0]; +#endif + PRINTF_FPHEX_FETCH (double, fpnum.dbl.d) - /* Check for special values: not a number or infinity. */ - if (isnan (fpnum.dbl.d)) - { - if (isupper (info->spec)) - { - special = "NAN"; - wspecial = L"NAN"; - } - else - { - special = "nan"; - wspecial = L"nan"; - } - } - else - { - if (isinf (fpnum.dbl.d)) - { - if (isupper (info->spec)) - { - special = "INF"; - wspecial = L"INF"; - } - else - { - special = "inf"; - wspecial = L"inf"; - } - } - } - negative = signbit (fpnum.dbl.d); - } +#undef PRINTF_FPHEX_FETCH if (special) { @@ -260,6 +242,11 @@ __printf_fphex (FILE *fp, return done; } +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + PRINT_FPHEX_FLOAT128; + else +#endif if (info->is_long_double == 0 || sizeof (double) == sizeof (long double)) { /* We have 52 bits of mantissa plus one implicit digit. Since @@ -329,8 +316,8 @@ __printf_fphex (FILE *fp, /* Look for trailing zeroes. */ if (! zero_mantissa) { - wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]]; - numend = &numbuf[sizeof numbuf / sizeof numbuf[0]]; + wnumend = array_end (wnumbuf); + numend = array_end (numbuf); while (wnumend[-1] == L'0') { --wnumend; diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c index 154ba9da1b..7e073c50d4 100644 --- a/stdio-common/printf_size.c +++ b/stdio-common/printf_size.c @@ -1,5 +1,5 @@ /* Print size value using units for orders of magnitude. - Copyright (C) 1997-2016 Free Software Foundation, Inc. + Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. Based on a proposal by Larry McVoy <lm@sgi.com>. @@ -24,18 +24,12 @@ #include <printf.h> #include <libioP.h> - -/* This defines make it possible to use the same code for GNU C library and - the GNU I/O library. */ #define PUT(f, s, n) _IO_sputn (f, s, n) #define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n)) -/* We use this file GNU C library and GNU I/O library. So make - names equal. */ #undef putc #define putc(c, f) (wide \ ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f)) -#define size_t _IO_size_t -#define FILE _IO_FILE + /* Macros for doing the actual output. */ @@ -104,6 +98,9 @@ __printf_size (FILE *fp, const struct printf_info *info, { union ieee754_double dbl; long double ldbl; +#if __HAVE_DISTINCT_FLOAT128 + _Float128 f128; +#endif } fpnum; const void *ptr = &fpnum; @@ -118,57 +115,45 @@ __printf_size (FILE *fp, const struct printf_info *info, int done = 0; int wide = info->wide; +#define PRINTF_SIZE_FETCH(FLOAT, VAR) \ + { \ + (VAR) = *(const FLOAT *) args[0]; \ + \ + /* Check for special values: not a number or infinity. */ \ + if (isnan (VAR)) \ + { \ + special = "nan"; \ + wspecial = L"nan"; \ + /* is_neg = 0; Already zero */ \ + } \ + else if (isinf (VAR)) \ + { \ + is_neg = signbit (VAR); \ + special = "inf"; \ + wspecial = L"inf"; \ + } \ + else \ + while ((VAR) >= divisor && tag[1] != '\0') \ + { \ + (VAR) /= divisor; \ + ++tag; \ + } \ + } + /* Fetch the argument value. */ +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + PRINTF_SIZE_FETCH (_Float128, fpnum.f128) + else +#endif #ifndef __NO_LONG_DOUBLE_MATH if (info->is_long_double && sizeof (long double) > sizeof (double)) - { - fpnum.ldbl = *(const long double *) args[0]; - - /* Check for special values: not a number or infinity. */ - if (isnan (fpnum.ldbl)) - { - special = "nan"; - wspecial = L"nan"; - // is_neg = 0; Already zero - } - else if (isinf (fpnum.ldbl)) - { - is_neg = signbit (fpnum.ldbl); - special = "inf"; - wspecial = L"inf"; - } - else - while (fpnum.ldbl >= divisor && tag[1] != '\0') - { - fpnum.ldbl /= divisor; - ++tag; - } - } + PRINTF_SIZE_FETCH (long double, fpnum.ldbl) else -#endif /* no long double */ - { - fpnum.dbl.d = *(const double *) args[0]; +#endif + PRINTF_SIZE_FETCH (double, fpnum.dbl.d) - /* Check for special values: not a number or infinity. */ - if (isnan (fpnum.dbl.d)) - { - special = "nan"; - wspecial = L"nan"; - // is_neg = 0; Already zero - } - else if (isinf (fpnum.dbl.d)) - { - is_neg = signbit (fpnum.dbl.d); - special = "inf"; - wspecial = L"inf"; - } - else - while (fpnum.dbl.d >= divisor && tag[1] != '\0') - { - fpnum.dbl.d /= divisor; - ++tag; - } - } +#undef PRINTF_SIZE_FETCH if (special) { diff --git a/stdio-common/psiginfo.c b/stdio-common/psiginfo.c index 96c6e91b2a..8f6c53aeb4 100644 --- a/stdio-common/psiginfo.c +++ b/stdio-common/psiginfo.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2016 Free Software Foundation, Inc. +/* Copyright (C) 2009-2018 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 @@ -15,6 +15,7 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <array_length.h> #include <errno.h> #include <libintl.h> #include <signal.h> @@ -116,7 +117,7 @@ psiginfo (const siginfo_t *pinfo, const char *s) case sig: \ base = C(codestrs_, sig).str; \ offarr = C (codes_, sig); \ - offarr_len = sizeof (C (codes_, sig)) / sizeof (C (codes_, sig)[0]);\ + offarr_len = array_length (C (codes_, sig)); \ break H (SIGILL); @@ -199,5 +200,5 @@ Signal generated by the completion of an I/O request"); fclose (fp); - write_not_cancel (STDERR_FILENO, buf, strlen (buf)); + __write_nocancel (STDERR_FILENO, buf, strlen (buf)); } diff --git a/stdio-common/psignal.c b/stdio-common/psignal.c index f391ada336..9642a679eb 100644 --- a/stdio-common/psignal.c +++ b/stdio-common/psignal.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/putw.c b/stdio-common/putw.c index a70d3a0d91..789cf0de3e 100644 --- a/stdio-common/putw.c +++ b/stdio-common/putw.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/reg-modifier.c b/stdio-common/reg-modifier.c index 9a9a678ab7..80f21e205c 100644 --- a/stdio-common/reg-modifier.c +++ b/stdio-common/reg-modifier.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2016 Free Software Foundation, Inc. +/* Copyright (C) 2009-2018 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 diff --git a/stdio-common/reg-printf.c b/stdio-common/reg-printf.c index cd64c2abdd..35db28aa33 100644 --- a/stdio-common/reg-printf.c +++ b/stdio-common/reg-printf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -32,6 +32,7 @@ __libc_lock_define_initialized (static, lock) int __register_printf_specifier (int, printf_function, printf_arginfo_size_function); +libc_hidden_proto (__register_printf_specifier) int __register_printf_function (int, printf_function, printf_arginfo_function); @@ -72,6 +73,7 @@ __register_printf_specifier (int spec, printf_function converter, return result; } +libc_hidden_def (__register_printf_specifier) weak_alias (__register_printf_specifier, register_printf_specifier) diff --git a/stdio-common/reg-type.c b/stdio-common/reg-type.c index aaaf46af30..aac53f088d 100644 --- a/stdio-common/reg-type.c +++ b/stdio-common/reg-type.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2016 Free Software Foundation, Inc. +/* Copyright (C) 2009-2018 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 diff --git a/stdio-common/remove.c b/stdio-common/remove.c index 7bbe476585..e01ba517da 100644 --- a/stdio-common/remove.c +++ b/stdio-common/remove.c @@ -1,5 +1,5 @@ /* ANSI C `remove' function to delete a file or directory. Stub version. - Copyright (C) 1995-2016 Free Software Foundation, Inc. + Copyright (C) 1995-2018 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 diff --git a/stdio-common/rename.c b/stdio-common/rename.c index 993a96f2bd..564e8852ac 100644 --- a/stdio-common/rename.c +++ b/stdio-common/rename.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/renameat.c b/stdio-common/renameat.c index 40698025b9..98c8f1d18b 100644 --- a/stdio-common/renameat.c +++ b/stdio-common/renameat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005-2016 Free Software Foundation, Inc. +/* Copyright (C) 2005-2018 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 @@ -22,7 +22,7 @@ /* Rename the file OLD relative to OLDFD to NEW relative to NEWFD. */ int -renameat (int oldfd, const char *old, int newfd, const char *new) +__renameat (int oldfd, const char *old, int newfd, const char *new) { if ((oldfd < 0 && oldfd != AT_FDCWD) || (newfd < 0 && newfd != AT_FDCWD)) { @@ -40,5 +40,6 @@ renameat (int oldfd, const char *old, int newfd, const char *new) return -1; } - +libc_hidden_def (__renameat) +weak_alias (__renameat, renameat) stub_warning (renameat) diff --git a/stdio-common/renameat2.c b/stdio-common/renameat2.c new file mode 100644 index 0000000000..c2cedcd2cb --- /dev/null +++ b/stdio-common/renameat2.c @@ -0,0 +1,30 @@ +/* Generic implementation of the renameat function. + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stdio.h> + +int +renameat2 (int oldfd, const char *old, int newfd, const char *new, + unsigned int flags) +{ + if (flags == 0) + return __renameat (oldfd, old, newfd, new); + __set_errno (EINVAL); + return -1; +} diff --git a/stdio-common/scanf.c b/stdio-common/scanf.c index c020bb85ba..e61b5f1ad3 100644 --- a/stdio-common/scanf.c +++ b/stdio-common/scanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/scanf11.c b/stdio-common/scanf11.c index fcf98464b4..1928da44cd 100644 --- a/stdio-common/scanf11.c +++ b/stdio-common/scanf11.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. diff --git a/stdio-common/scanf14.c b/stdio-common/scanf14.c index cffccb0b19..2bcd9c9893 100644 --- a/stdio-common/scanf14.c +++ b/stdio-common/scanf14.c @@ -2,7 +2,7 @@ #include <stdlib.h> #include <string.h> #include <wchar.h> -#include <libc-internal.h> +#include <libc-diag.h> #define FAIL() \ do { \ diff --git a/stdio-common/scanf4.c b/stdio-common/scanf4.c index 9bb14bb16b..7a2abec89b 100644 --- a/stdio-common/scanf4.c +++ b/stdio-common/scanf4.c @@ -1,6 +1,6 @@ #include <stdio.h> #include <stdlib.h> -#include <libc-internal.h> +#include <libc-diag.h> int main(int arc, char *argv[]) diff --git a/stdio-common/scanf7.c b/stdio-common/scanf7.c index 53ddf4cb09..f568738d7e 100644 --- a/stdio-common/scanf7.c +++ b/stdio-common/scanf7.c @@ -1,6 +1,6 @@ #include <stdio.h> #include <stdlib.h> -#include <libc-internal.h> +#include <libc-diag.h> int main (int argc, char *argv[]) diff --git a/stdio-common/siglist.c b/stdio-common/siglist.c index 9dbceb7e39..722604f4c2 100644 --- a/stdio-common/siglist.c +++ b/stdio-common/siglist.c @@ -1,5 +1,5 @@ /* Define list of all signal numbers and their names. - Copyright (C) 1997-2016 Free Software Foundation, Inc. + Copyright (C) 1997-2018 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 diff --git a/stdio-common/snprintf.c b/stdio-common/snprintf.c index a3cc518976..29a169b08b 100644 --- a/stdio-common/snprintf.c +++ b/stdio-common/snprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -35,4 +35,5 @@ __snprintf (char *s, size_t maxlen, const char *format, ...) return done; } +libc_hidden_def (__snprintf) ldbl_weak_alias (__snprintf, snprintf) diff --git a/stdio-common/sprintf.c b/stdio-common/sprintf.c index 76f51f6c22..bf5671dde9 100644 --- a/stdio-common/sprintf.c +++ b/stdio-common/sprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/sscanf.c b/stdio-common/sscanf.c index 993636120b..88cd641798 100644 --- a/stdio-common/sscanf.c +++ b/stdio-common/sscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/stdio_ext.h b/stdio-common/stdio_ext.h index eca2b19204..62aa5fdfed 100644 --- a/stdio-common/stdio_ext.h +++ b/stdio-common/stdio_ext.h @@ -1,5 +1,5 @@ /* Functions to access FILE structure internals. - Copyright (C) 2000-2016 Free Software Foundation, Inc. + Copyright (C) 2000-2018 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 diff --git a/stdio-common/stdio_lim.h.in b/stdio-common/stdio_lim.h.in index dc9cdbedc2..9d18b16ace 100644 --- a/stdio-common/stdio_lim.h.in +++ b/stdio-common/stdio_lim.h.in @@ -1,4 +1,4 @@ -/* Copyright (C) 1994-2016 Free Software Foundation, Inc. +/* Copyright (C) 1994-2018 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 @@ -15,28 +15,25 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#if !defined _STDIO_H && !defined __need_FOPEN_MAX && !defined __need_IOV_MAX +#ifndef _BITS_STDIO_LIM_H +#define _BITS_STDIO_LIM_H 1 + +#ifndef _STDIO_H # error "Never include <bits/stdio_lim.h> directly; use <stdio.h> instead." #endif -#ifdef _STDIO_H -# define L_tmpnam @L_tmpnam@ -# define TMP_MAX @TMP_MAX@ -# define FILENAME_MAX @FILENAME_MAX@ +#define L_tmpnam @L_tmpnam@ +#define TMP_MAX @TMP_MAX@ +#define FILENAME_MAX @FILENAME_MAX@ -# ifdef __USE_POSIX -# define L_ctermid @L_ctermid@ -# if !defined __USE_XOPEN2K || defined __USE_GNU -# define L_cuserid @L_cuserid@ -# endif +#ifdef __USE_POSIX +# define L_ctermid @L_ctermid@ +# if !defined __USE_XOPEN2K || defined __USE_GNU +# define L_cuserid @L_cuserid@ # endif #endif -#if defined __need_FOPEN_MAX || defined _STDIO_H -# undef FOPEN_MAX -# define FOPEN_MAX @FOPEN_MAX@ -#endif +#undef FOPEN_MAX +#define FOPEN_MAX @FOPEN_MAX@ -#if defined __need_IOV_MAX && !defined IOV_MAX -@define_IOV_MAX@ -#endif +#endif /* bits/stdio_lim.h */ diff --git a/stdio-common/tempnam.c b/stdio-common/tempnam.c index 7a53262e9a..5e64482b48 100644 --- a/stdio-common/tempnam.c +++ b/stdio-common/tempnam.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/tempname.c b/stdio-common/tempname.c index 07102c51e7..015c1d0334 100644 --- a/stdio-common/tempname.c +++ b/stdio-common/tempname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/test-fseek.c b/stdio-common/test-fseek.c index 455b2bea92..17cd90b053 100644 --- a/stdio-common/test-fseek.c +++ b/stdio-common/test-fseek.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -17,7 +17,7 @@ #include <stdio.h> -#define TESTFILE "/tmp/test.dat" +#define TESTFILE OBJPFX "test.dat" static int do_test (void) diff --git a/stdio-common/test-popen.c b/stdio-common/test-popen.c index caf5731940..206f212468 100644 --- a/stdio-common/test-popen.c +++ b/stdio-common/test-popen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997-2016 Free Software Foundation, Inc. +/* Copyright (C) 1997-2018 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 @@ -59,7 +59,7 @@ do_test (void) the perhaps incompatible new shared libraries. */ unsetenv ("LD_LIBRARY_PATH"); - output = popen ("/bin/cat >/tmp/tstpopen.tmp", "w"); + output = popen ("/bin/cat >" OBJPFX "tstpopen.tmp", "w"); if (output == NULL) { perror ("popen"); @@ -69,10 +69,10 @@ do_test (void) write_data (output); wstatus = pclose (output); printf ("writing pclose returned %d\n", wstatus); - input = popen ("/bin/cat /tmp/tstpopen.tmp", "r"); + input = popen ("/bin/cat " OBJPFX "tstpopen.tmp", "r"); if (input == NULL) { - perror ("/tmp/tstpopen.tmp"); + perror (OBJPFX "tstpopen.tmp"); puts ("Test FAILED!"); exit (1); } @@ -80,7 +80,7 @@ do_test (void) rstatus = pclose (input); printf ("reading pclose returned %d\n", rstatus); - remove ("/tmp/tstpopen.tmp"); + remove (OBJPFX "tstpopen.tmp"); errno = 0; output = popen ("/bin/cat", "m"); diff --git a/stdio-common/test-vfprintf.c b/stdio-common/test-vfprintf.c index b8829eaf10..bc6b0a54bb 100644 --- a/stdio-common/test-vfprintf.c +++ b/stdio-common/test-vfprintf.c @@ -1,5 +1,5 @@ /* Tests of *printf for very large strings. - Copyright (C) 2000-2016 Free Software Foundation, Inc. + Copyright (C) 2000-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2000. @@ -17,6 +17,7 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <array_length.h> #include <locale.h> #include <mcheck.h> #include <stdint.h> @@ -25,15 +26,13 @@ #include <string.h> #include <unistd.h> #include <sys/stat.h> -#include <libc-internal.h> +#include <libc-diag.h> const char *locs[] = { "C", "de_DE.ISO-8859-1", "de_DE.UTF-8", "ja_JP.EUC-JP" }; -#define nlocs (sizeof (locs) / sizeof (locs[0])) - char large[50000]; @@ -56,7 +55,7 @@ do_test (void) } unlink (buf); - for (i = 0; i < nlocs; ++i) + for (i = 0; i < array_length (locs); ++i) { FILE *fp; struct stat st; diff --git a/stdio-common/test_rdwr.c b/stdio-common/test_rdwr.c index 3b994d130b..348987351f 100644 --- a/stdio-common/test_rdwr.c +++ b/stdio-common/test_rdwr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -38,7 +38,7 @@ main (int argc, char **argv) else name = *argv; - (void) sprintf (filename, "/tmp/%s.test", name); + (void) sprintf (filename, OBJPFX "%s.test", name); f = fopen (filename, "w+"); if (f == NULL) diff --git a/stdio-common/tmpfile.c b/stdio-common/tmpfile.c index d4720a4e9a..5ffecae60c 100644 --- a/stdio-common/tmpfile.c +++ b/stdio-common/tmpfile.c @@ -1,5 +1,5 @@ /* Open a stdio stream on an anonymous temporary file. Generic/POSIX version. - Copyright (C) 1991-2016 Free Software Foundation, Inc. + Copyright (C) 1991-2018 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 @@ -34,23 +34,31 @@ FILE * tmpfile (void) { - char buf[FILENAME_MAX]; int fd; FILE *f; - - if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0)) - return NULL; int flags = 0; #ifdef FLAGS flags = FLAGS; #endif - fd = __gen_tempname (buf, 0, flags, __GT_FILE); + + /* First try a system specific method. */ + fd = __gen_tempfd (flags); + if (fd < 0) - return NULL; + { + char buf[FILENAME_MAX]; + + if (__path_search (buf, sizeof buf, NULL, "tmpf", 0)) + return NULL; + + fd = __gen_tempname (buf, 0, flags, __GT_FILE); + if (fd < 0) + return NULL; - /* Note that this relies on the Unix semantics that - a file is not really removed until it is closed. */ - (void) __unlink (buf); + /* Note that this relies on the Unix semantics that + a file is not really removed until it is closed. */ + (void) __unlink (buf); + } if ((f = __fdopen (fd, "w+b")) == NULL) __close (fd); diff --git a/stdio-common/tmpfile64.c b/stdio-common/tmpfile64.c index 6864c33bbe..36f852d258 100644 --- a/stdio-common/tmpfile64.c +++ b/stdio-common/tmpfile64.c @@ -1,5 +1,5 @@ /* Open a stdio stream on an anonymous, large temporary file. Generic version. - Copyright (C) 2012-2016 Free Software Foundation, Inc. + Copyright (C) 2012-2018 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 diff --git a/stdio-common/tmpnam.c b/stdio-common/tmpnam.c index 6f0b1d596e..9b0b6114a3 100644 --- a/stdio-common/tmpnam.c +++ b/stdio-common/tmpnam.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/tmpnam_r.c b/stdio-common/tmpnam_r.c index aa26737060..baba861667 100644 --- a/stdio-common/tmpnam_r.c +++ b/stdio-common/tmpnam_r.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 diff --git a/stdio-common/tst-fdopen.c b/stdio-common/tst-fdopen.c index e70a0cd6a5..136fff5858 100644 --- a/stdio-common/tst-fdopen.c +++ b/stdio-common/tst-fdopen.c @@ -1,6 +1,7 @@ /* Test for fdopen bugs. */ #include <stdio.h> +#include <stdlib.h> #include <unistd.h> #include <fcntl.h> @@ -18,12 +19,18 @@ char buffer[256]; int main (int argc, char *argv[]) { - char *name; + char name[] = "/tmp/tst-fdopen.XXXXXX"; FILE *fp = NULL; int retval = 0; int fd; - name = tmpnam (NULL); + fd = mkstemp (name); + if (fd == -1) + { + printf ("mkstemp failed: %m\n"); + return 1; + } + close (fd); fp = fopen (name, "w"); assert (fp != NULL) fputs ("foobar and baz", fp); diff --git a/stdio-common/tst-fgets.c b/stdio-common/tst-fgets.c index 0aa9030e3a..912b7068eb 100644 --- a/stdio-common/tst-fgets.c +++ b/stdio-common/tst-fgets.c @@ -1,5 +1,5 @@ /* Derived from the test case in - http://sourceware.org/bugzilla/show_bug.cgi?id=713. */ + https://sourceware.org/bugzilla/show_bug.cgi?id=713. */ #include <stdio.h> static int diff --git a/stdio-common/tst-fileno.c b/stdio-common/tst-fileno.c index a1a05a9d1b..92ccbda5b5 100644 --- a/stdio-common/tst-fileno.c +++ b/stdio-common/tst-fileno.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1994-2016 Free Software Foundation, Inc. +/* Copyright (C) 1994-2018 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 diff --git a/stdio-common/tst-fmemopen.c b/stdio-common/tst-fmemopen.c index cd151cc173..b030282273 100644 --- a/stdio-common/tst-fmemopen.c +++ b/stdio-common/tst-fmemopen.c @@ -1,5 +1,5 @@ /* basic fmemopen interface testing. - Copyright (C) 2014-2016 Free Software Foundation, Inc. + Copyright (C) 2014-2018 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 diff --git a/stdio-common/tst-fmemopen2.c b/stdio-common/tst-fmemopen2.c index 9d0891dcd4..ac1e87a5e0 100644 --- a/stdio-common/tst-fmemopen2.c +++ b/stdio-common/tst-fmemopen2.c @@ -1,5 +1,5 @@ /* fmemopen tests. - Copyright (C) 2015-2016 Free Software Foundation, Inc. + Copyright (C) 2015-2018 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 @@ -21,6 +21,7 @@ #include <stdio.h> #include <string.h> #include <sys/types.h> +#include <stdint.h> #include <errno.h> /* Check fmemopen with user provided buffer open for write. */ diff --git a/stdio-common/tst-fmemopen3.c b/stdio-common/tst-fmemopen3.c index 250f9ecc75..7878886e3d 100644 --- a/stdio-common/tst-fmemopen3.c +++ b/stdio-common/tst-fmemopen3.c @@ -1,5 +1,5 @@ /* fmemopen tests for append and read mode. - Copyright (C) 2015-2016 Free Software Foundation, Inc. + Copyright (C) 2015-2018 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 @@ -25,8 +25,13 @@ static void print_buffer (const char *s, size_t n) { size_t i; + printf ("{"); for (i=0; i<n; ++i) - printf ("0x%02X (%c), ", s[i], s[i]); + { + printf ("0x%02X (%c)", s[i], s[i]); + if (i != n) + printf (", "); + } } /* This test check append mode initial position (a/a+) based on POSIX defition @@ -186,6 +191,112 @@ do_test_read_seek_negative (void) } static int +do_test_write_append_2 (const char *str) +{ + char buf[10]; + size_t strn = strlen (str); + strcpy (buf, str); + + FILE *fp = fmemopen (buf, sizeof (buf), "a+"); + size_t r = ftell (fp); + size_t e = strlen (buf); + if (r != e) + { + printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e); + return 1; + } + + if (fseek (fp, 0, SEEK_SET) == -1) + { + printf ("%s: fseek returned -1\n", __FUNCTION__); + return 1; + } + + int gr; + for (int i=0; i<strn; ++i) + { + if ((gr = getc (fp)) != str[i]) + { + printf ("%s: getc failed returned %d, expected %d\n", __FUNCTION__, + gr, str[i]); + return 1; + } + } + if ((gr = getc (fp)) != EOF) + { + printf ("%s: getc failed returned %d, expected EOF\n", __FUNCTION__, + gr); + return 1; + } + + if (fseek (fp, e+1, SEEK_SET) == -1) + { + printf ("%s: fseek returned -1\n", __FUNCTION__); + return 1; + } + + if ((r = ftell (fp)) != e+1) + { + printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+1); + return 1; + } + + if ((gr = getc (fp)) != EOF) + { + printf ("%s: getc failed returned %i\n", __FUNCTION__, gr); + return 1; + } + + /* Check if internal position is not changed with a getc returning EOF. */ + if ((r = ftell (fp)) != e+1) + { + printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+1); + return 1; + } + + if (fseek (fp, 0, SEEK_CUR) == -1) + { + printf ("%s: fseek returned -1\n", __FUNCTION__); + return 1; + } + + /* This should be overwritten by fprintf + fflush. */ + buf[e+2] = 'X'; + + if ((r = fprintf (fp, "%d", 101)) != 3) + { + printf ("%s: fprintf returned %zu, expected %d\n", __FUNCTION__, r, 3); + return 1; + } + + fflush (fp); + + /* Check if internal position is changed by 3 (strlen of '101'). */ + if ((r = ftell (fp)) != e+3) + { + printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+3); + return 1; + } + + char exp[20]; + sprintf (exp, "%s%d", str, 101); + if (memcmp (buf, exp, strlen (exp)) != 0) + { + printf ("%s: check failed:", __FUNCTION__); + printf ("\nexpected: "); + print_buffer (buf, sizeof (buf)); + printf ("\nbuffer: "); + print_buffer (exp, sizeof (exp)); + printf ("\n"); + return 1; + } + + fclose(fp); + + return 0; +} + +static int do_test (void) { int ret = 0; @@ -199,6 +310,11 @@ do_test (void) ret += do_test_read_seek_negative (); + /* First test plus addend will fit in the define buffer of size 10. */ + ret += do_test_write_append_2 ("test"); + /* The second test will also fit, but not the final '\0'. */ + ret += do_test_write_append_2 ("testing"); + return ret; } diff --git a/stdio-common/tst-fmemopen4.c b/stdio-common/tst-fmemopen4.c new file mode 100644 index 0000000000..a48fa361c4 --- /dev/null +++ b/stdio-common/tst-fmemopen4.c @@ -0,0 +1,71 @@ +/* fmemopen tests for BZ#1930 and BZ#20005. + Copyright (C) 2016-2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> + + +/* Check if fflush does not reset the file position. */ +static int +do_test (void) +{ + char buffer[500] = "x"; + + FILE *stream = fmemopen (buffer, sizeof (buffer), "r+"); + if (stream == NULL) + { + printf ("error: fmemopen could not open stream\n"); + return 1; + } + + const char test[] = "test"; + + size_t r = fwrite (test, sizeof (char), sizeof (test), stream); + if (r != sizeof (test)) + { + printf ("error: fwrite returned %zu, expected %zu\n", r, sizeof(test)); + return 1; + } + + r = ftell (stream); + if (r != sizeof (test)) + { + printf ("error: ftell return %zu, expected %zu\n", r, sizeof(test)); + return 1; + } + + if (fflush (stream) != 0) + { + printf ("error: fflush failed\n"); + return 1; + } + + r = ftell (stream); + if (r != sizeof (test)) + { + printf ("error: ftell return %zu, expected %zu\n", r, sizeof(test)); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdio-common/tst-fphex-wide.c b/stdio-common/tst-fphex-wide.c index 1f4797c9f8..04c27ba39d 100644 --- a/stdio-common/tst-fphex-wide.c +++ b/stdio-common/tst-fphex-wide.c @@ -1,6 +1,6 @@ /* Test program for %a wprintf formats. This file is part of the GNU C Library. - Copyright (C) 2012-2016 Free Software Foundation, Inc. + Copyright (C) 2012-2018 Free Software Foundation, Inc. Contributed by Marek Polacek <polacek@redhat.com>, 2012. The GNU C Library is free software; you can redistribute it and/or diff --git a/stdio-common/tst-fphex.c b/stdio-common/tst-fphex.c index c2e8961d62..efba482537 100644 --- a/stdio-common/tst-fphex.c +++ b/stdio-common/tst-fphex.c @@ -1,5 +1,6 @@ /* Test program for %a printf formats. */ +#include <array_length.h> #include <stdio.h> #include <string.h> @@ -49,12 +50,10 @@ do_test (void) const struct testcase *t; int result = 0; - for (t = testcases; - t < &testcases[sizeof testcases / sizeof testcases[0]]; - ++t) + for (t = testcases; t < array_end (testcases); ++t) { CHAR_T buf[1024]; - int n = SPRINT (buf, sizeof buf / sizeof (buf[0]), t->fmt, t->value); + int n = SPRINT (buf, array_length (buf), t->fmt, t->value); if (n != STR_LEN (t->expect) || STR_CMP (buf, t->expect) != 0) { PRINT (L_("" S "\tExpected \"" S "\" (%Zu)\n\tGot \"" diff --git a/stdio-common/tst-fseek.c b/stdio-common/tst-fseek.c index 2598edd0b3..9d5f7466f6 100644 --- a/stdio-common/tst-fseek.c +++ b/stdio-common/tst-fseek.c @@ -1,5 +1,5 @@ /* Tests of fseek and fseeko. - Copyright (C) 2000-2016 Free Software Foundation, Inc. + Copyright (C) 2000-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2000. diff --git a/stdio-common/tst-fwrite.c b/stdio-common/tst-fwrite.c index 2986c8932a..1db10d0f6a 100644 --- a/stdio-common/tst-fwrite.c +++ b/stdio-common/tst-fwrite.c @@ -1,5 +1,5 @@ /* Derived from the test case in - http://sourceware.org/bugzilla/show_bug.cgi?id=1078. */ + https://sourceware.org/bugzilla/show_bug.cgi?id=1078. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> diff --git a/stdio-common/tst-gets.c b/stdio-common/tst-gets.c index 073bc54984..7ecbee2ec8 100644 --- a/stdio-common/tst-gets.c +++ b/stdio-common/tst-gets.c @@ -1,5 +1,5 @@ /* Tests for gets. - Copyright (C) 2001-2016 Free Software Foundation, Inc. + Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -17,6 +17,11 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +/* This file tests gets. Force it to be declared. */ +#include <features.h> +#undef __GLIBC_USE_DEPRECATED_GETS +#define __GLIBC_USE_DEPRECATED_GETS 1 + #include <stdio.h> #include <string.h> diff --git a/stdio-common/tst-long-dbl-fphex.c b/stdio-common/tst-long-dbl-fphex.c index 6241dfd48e..33dc73190d 100644 --- a/stdio-common/tst-long-dbl-fphex.c +++ b/stdio-common/tst-long-dbl-fphex.c @@ -1,5 +1,5 @@ /* This file is part of the GNU C Library. - Copyright (C) 2012-2016 Free Software Foundation, Inc. + Copyright (C) 2012-2018 Free Software Foundation, Inc. Contributed by Marek Polacek <polacek@redhat.com>, 2012. The GNU C Library is free software; you can redistribute it and/or @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <array_length.h> #include <wchar.h> /* Prototype for our test function. */ @@ -28,9 +29,9 @@ do_test (void) int result = 0; const long double x = 24.5; wchar_t a[16]; - swprintf (a, sizeof a / sizeof a[0], L"%La\n", x); + swprintf (a, array_length (a), L"%La\n", x); wchar_t A[16]; - swprintf (A, sizeof A / sizeof A[0], L"%LA\n", x); + swprintf (A, array_length (a), L"%LA\n", x); /* Here wprintf can return four valid variants. We must accept all of them. */ diff --git a/stdio-common/tst-popen.c b/stdio-common/tst-popen.c index 94cb59d1c6..87d1c37679 100644 --- a/stdio-common/tst-popen.c +++ b/stdio-common/tst-popen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2016 Free Software Foundation, Inc. +/* Copyright (C) 2004-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. diff --git a/stdio-common/tst-printf-bz18872.sh b/stdio-common/tst-printf-bz18872.sh index b96695b400..8b2aec42d9 100644 --- a/stdio-common/tst-printf-bz18872.sh +++ b/stdio-common/tst-printf-bz18872.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright (C) 2015-2016 Free Software Foundation, Inc. +# Copyright (C) 2015-2018 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 diff --git a/stdio-common/tst-printf-round.c b/stdio-common/tst-printf-round.c index 93a29b509b..d8b6345c39 100644 --- a/stdio-common/tst-printf-round.c +++ b/stdio-common/tst-printf-round.c @@ -1,5 +1,5 @@ /* Test for correct rounding of printf floating-point output. - Copyright (C) 2012-2016 Free Software Foundation, Inc. + Copyright (C) 2012-2018 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 @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <array_length.h> #include <fenv.h> #include <stdio.h> #include <string.h> @@ -167,7 +168,7 @@ do_test (void) int save_round_mode __attribute__ ((unused)) = fegetround (); int result = 0; - for (size_t i = 0; i < sizeof (dec_tests) / sizeof (dec_tests[0]); i++) + for (size_t i = 0; i < array_length (dec_tests); i++) { result |= test_dec_in_one_mode (dec_tests[i].d, dec_tests[i].fmt, dec_tests[i].rn, "default rounding mode"); @@ -197,7 +198,7 @@ do_test (void) #endif } - for (size_t i = 0; i < sizeof (hex_tests) / sizeof (hex_tests[0]); i++) + for (size_t i = 0; i < array_length (hex_tests); i++) { result |= test_hex_in_one_mode (hex_tests[i].d, hex_tests[i].fmt, hex_tests[i].rn, "default rounding mode"); diff --git a/stdio-common/tst-printf.c b/stdio-common/tst-printf.c index 2896b18ecd..70d9e584b3 100644 --- a/stdio-common/tst-printf.c +++ b/stdio-common/tst-printf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -26,12 +26,18 @@ #endif #include <float.h> -#include <libc-internal.h> +#include <libc-diag.h> /* This whole file is picayune tests of corner cases of printf format strings. The compiler warnings are not useful here. */ DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat"); +#if __GNUC_PREREQ (7, 0) +/* Compiler warnings about snprintf output truncation should also be + ignored. */ +DIAG_IGNORE_NEEDS_COMMENT (7.0, "-Wformat-truncation"); +#endif + static void rfg1 (void); static void rfg2 (void); static void rfg3 (void); @@ -63,75 +69,7 @@ fmtst2chk (const char *fmt) (void) printf(fmt, 4, 4, 0x12); (void) printf("'\n"); } - -/* This page is covered by the following copyright: */ - -/* (C) Copyright C E Chew - * - * Feel free to copy, use and distribute this software provided: - * - * 1. you do not pretend that you wrote it - * 2. you leave this copyright notice intact. - */ - -/* - * Extracted from exercise.c for glibc-1.05 bug report by Bruce Evans. - */ - -#define DEC -123 -#define INT 255 -#define UNS (~0) - -/* Formatted Output Test - * - * This exercises the output formatting code. - */ -static void -fp_test (void) -{ - int i, j, k, l; - char buf[7]; - char *prefix = buf; - char tp[20]; - - puts("\nFormatted output test"); - printf("prefix 6d 6o 6x 6X 6u\n"); - strcpy(prefix, "%"); - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) { - for (k = 0; k < 2; k++) { - for (l = 0; l < 2; l++) { - strcpy(prefix, "%"); - if (i == 0) strcat(prefix, "-"); - if (j == 0) strcat(prefix, "+"); - if (k == 0) strcat(prefix, "#"); - if (l == 0) strcat(prefix, "0"); - printf("%5s |", prefix); - strcpy(tp, prefix); - strcat(tp, "6d |"); - printf(tp, DEC); - strcpy(tp, prefix); - strcat(tp, "6o |"); - printf(tp, INT); - strcpy(tp, prefix); - strcat(tp, "6x |"); - printf(tp, INT); - strcpy(tp, prefix); - strcat(tp, "6X |"); - printf(tp, INT); - strcpy(tp, prefix); - strcat(tp, "6u |"); - printf(tp, UNS); - printf("\n"); - } - } - } - } - printf("%10s\n", (char *) NULL); - printf("%-10s\n", (char *) NULL); -} - static int do_test (void) { @@ -175,6 +113,8 @@ I am ready for my first lesson today."; printf("null string:\t\"%s\"\n", (char *)NULL); printf("limited string:\t\"%.22s\"\n", longstr); + printf("a-style max:\t\"%a\"\n", DBL_MAX); + printf("a-style -max:\t\"%a\"\n", -DBL_MAX); printf("e-style >= 1:\t\"%e\"\n", 12.34); printf("e-style >= .1:\t\"%e\"\n", 0.1234); printf("e-style < .1:\t\"%e\"\n", 0.001234); @@ -229,8 +169,8 @@ I am ready for my first lesson today."; snprintf(buf2, sizeof(buf2), "%.999999u", 10)); } - fp_test (); - + printf("%.8f\n", DBL_MAX); + printf("%.8f\n", -DBL_MAX); printf ("%e should be 1.234568e+06\n", 1234567.8); printf ("%f should be 1234567.800000\n", 1234567.8); printf ("%g should be 1.23457e+06\n", 1234567.8); diff --git a/stdio-common/tst-printf.sh b/stdio-common/tst-printf.sh index 5755a1bc0a..b543cc646c 100644 --- a/stdio-common/tst-printf.sh +++ b/stdio-common/tst-printf.sh @@ -1,6 +1,6 @@ #!/bin/sh # Testing of printf. -# Copyright (C) 2000-2016 Free Software Foundation, Inc. +# Copyright (C) 2000-2018 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 @@ -57,6 +57,8 @@ space-padded string: " Hi, Z." left-adjusted S string: "Hi, Z. " null string: "(null)" limited string: "Good morning, Doctor C" +a-style max: "0x1.fffffffffffffp+1023" +a-style -max: "-0x1.fffffffffffffp+1023" e-style >= 1: "1.234000e+01" e-style >= .1: "1.234000e-01" e-style < .1: "1.234000e-03" @@ -103,27 +105,8 @@ something really insane: 1.00000000000000000000000000000000000000000000000000000 | 123456.0000| 1.2346e+05| 1.235e+05| snprintf ("%30s", "foo") == 30, " " snprintf ("%.999999u", 10) == 999999 - -Formatted output test -prefix 6d 6o 6x 6X 6u -%-+#0 |-123 |0377 |0xff |0XFF |4294967295 | - %-+# |-123 |0377 |0xff |0XFF |4294967295 | - %-+0 |-123 |377 |ff |FF |4294967295 | - %-+ |-123 |377 |ff |FF |4294967295 | - %-#0 |-123 |0377 |0xff |0XFF |4294967295 | - %-# |-123 |0377 |0xff |0XFF |4294967295 | - %-0 |-123 |377 |ff |FF |4294967295 | - %- |-123 |377 |ff |FF |4294967295 | - %+#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 | - %+# | -123 | 0377 | 0xff | 0XFF |4294967295 | - %+0 |-00123 |000377 |0000ff |0000FF |4294967295 | - %+ | -123 | 377 | ff | FF |4294967295 | - %#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 | - %# | -123 | 0377 | 0xff | 0XFF |4294967295 | - %0 |-00123 |000377 |0000ff |0000FF |4294967295 | - % | -123 | 377 | ff | FF |4294967295 | - (null) -(null) +179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000 +-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000 1.234568e+06 should be 1.234568e+06 1234567.800000 should be 1234567.800000 1.23457e+06 should be 1.23457e+06 @@ -173,6 +156,8 @@ space-padded string: " Hi, Z." left-adjusted S string: "Hi, Z. " null string: "(null)" limited string: "Good morning, Doctor C" +a-style max: "0x1.fffffffffffffp+1023" +a-style -max: "-0x1.fffffffffffffp+1023" e-style >= 1: "1.234000e+01" e-style >= .1: "1.234000e-01" e-style < .1: "1.234000e-03" @@ -219,27 +204,8 @@ something really insane: 1.00000000000000000000000000000000000000000000000000000 | 123456.0000| 1.2346e+05| 1.235e+05| snprintf ("%30s", "foo") == 30, " " snprintf ("%.999999u", 10) == 999999 - -Formatted output test -prefix 6d 6o 6x 6X 6u -%-+#0 |-123 |0377 |0xff |0XFF |4294967295 | - %-+# |-123 |0377 |0xff |0XFF |4294967295 | - %-+0 |-123 |377 |ff |FF |4294967295 | - %-+ |-123 |377 |ff |FF |4294967295 | - %-#0 |-123 |0377 |0xff |0XFF |4294967295 | - %-# |-123 |0377 |0xff |0XFF |4294967295 | - %-0 |-123 |377 |ff |FF |4294967295 | - %- |-123 |377 |ff |FF |4294967295 | - %+#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 | - %+# | -123 | 0377 | 0xff | 0XFF |4294967295 | - %+0 |-00123 |000377 |0000ff |0000FF |4294967295 | - %+ | -123 | 377 | ff | FF |4294967295 | - %#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 | - %# | -123 | 0377 | 0xff | 0XFF |4294967295 | - %0 |-00123 |000377 |0000ff |0000FF |4294967295 | - % | -123 | 377 | ff | FF |4294967295 | - (null) -(null) +179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000 +-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000 1.234568e+06 should be 1.234568e+06 1234567.800000 should be 1234567.800000 1.23457e+06 should be 1.23457e+06 diff --git a/stdio-common/tst-printfsz-islongdouble.c b/stdio-common/tst-printfsz-islongdouble.c new file mode 100644 index 0000000000..a6a534bb3d --- /dev/null +++ b/stdio-common/tst-printfsz-islongdouble.c @@ -0,0 +1,51 @@ +/* Test for the behaviour of 'is_long_double' in printf_size. + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <printf.h> +#include <stdio.h> +#include <string.h> + +#include <support/check.h> + +static int +do_test (void) +{ + double d = 2000; + double *dptr = &d; + long double ld = 4000; + long double *ldptr = & ld; + struct printf_info info; + + memset (&info, 0, sizeof (info)); + info.spec = L'f'; + + /* Print a value with double type. */ + printf_size (stdout, &info, (void *) &dptr); + + /* Printf a value with long double type. */ + info.is_long_double = 1; + printf_size (stdout, &info, (void *) &ldptr); + + /* Setting both 'is_long_double' and 'is_binary128' to one is out of + the scope of this test, because such configuration is only valid + when _Float128 and long double are ABI-distinct (which is not + always true in this arch-independent test). */ + return 0; +} + +#include <support/test-driver.c> diff --git a/stdio-common/tst-printfsz-islongdouble.sh b/stdio-common/tst-printfsz-islongdouble.sh new file mode 100644 index 0000000000..6eda634844 --- /dev/null +++ b/stdio-common/tst-printfsz-islongdouble.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# Test for the behaviour of 'is_binary128' in printf_size. +# Copyright (C) 2018 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 +# <http://www.gnu.org/licenses/>. + +set -e + +test_program=$1; shift +test_program_prefix=$1; shift +test_program_output=$1; shift + +status=0 + +${test_program_prefix} \ + ${test_program} \ + > ${test_program_output} || status=1 + +echo -n "2k4k" | cmp - ${test_program_output} > /dev/null 2>&1 || +{ + status=1 + echo "*** output comparison failed" +} + +exit $status diff --git a/stdio-common/tst-printfsz.c b/stdio-common/tst-printfsz.c index 8a3385f94d..47aa8536b3 100644 --- a/stdio-common/tst-printfsz.c +++ b/stdio-common/tst-printfsz.c @@ -2,7 +2,7 @@ #include <printf.h> #include <stdio.h> #include <string.h> -#include <libc-internal.h> +#include <libc-diag.h> #define V 12345678.12345678 diff --git a/stdio-common/tst-put-error.c b/stdio-common/tst-put-error.c index 86e7fbd104..4366ed6f2c 100644 --- a/stdio-common/tst-put-error.c +++ b/stdio-common/tst-put-error.c @@ -1,6 +1,6 @@ /* Verify that print functions return error when there is an I/O error. - Copyright (C) 2005-2016 Free Software Foundation, Inc. + Copyright (C) 2005-2018 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 diff --git a/stdio-common/tst-renameat2.c b/stdio-common/tst-renameat2.c new file mode 100644 index 0000000000..958b0918d6 --- /dev/null +++ b/stdio-common/tst-renameat2.c @@ -0,0 +1,204 @@ +/* Linux implementation for renameat2 function. + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <array_length.h> +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <support/check.h> +#include <support/support.h> +#include <support/temp_file.h> +#include <support/xunistd.h> +#include <unistd.h> + +/* Directory with the temporary files. */ +static char *directory; +static int directory_fd; + +/* Paths within that directory. */ +static char *old_path; /* File is called "old". */ +static char *new_path; /* File is called "new". */ + +/* Subdirectory within the directory above. */ +static char *subdirectory; +int subdirectory_fd; + +/* And a pathname in that directory (called "file"). */ +static char *subdir_path; + +static void +prepare (int argc, char **argv) +{ + directory = support_create_temp_directory ("tst-renameat2-"); + directory_fd = xopen (directory, O_RDONLY | O_DIRECTORY, 0); + old_path = xasprintf ("%s/old", directory); + add_temp_file (old_path); + new_path = xasprintf ("%s/new", directory); + add_temp_file (new_path); + subdirectory = xasprintf ("%s/subdir", directory); + xmkdir (subdirectory, 0777); + add_temp_file (subdirectory); + subdirectory_fd = xopen (subdirectory, O_RDONLY | O_DIRECTORY, 0); + subdir_path = xasprintf ("%s/file", subdirectory); + add_temp_file (subdir_path); +} + +/* Delete all files, preparing a clean slate for the next test. */ +static void +delete_all_files (void) +{ + char *files[] = { old_path, new_path, subdir_path }; + for (size_t i = 0; i < array_length (files); ++i) + if (unlink (files[i]) != 0 && errno != ENOENT) + FAIL_EXIT1 ("unlink (\"%s\"): %m", files[i]); +} + +/* Return true if PATH exists in the file system. */ +static bool +file_exists (const char *path) +{ + return access (path, F_OK) == 0; +} + +/* Check that PATH exists and has size EXPECTED_SIZE. */ +static void +check_size (const char *path, off64_t expected_size) +{ + struct stat64 st; + xstat (path, &st); + if (st.st_size != expected_size) + FAIL_EXIT1 ("file \"%s\": expected size %lld, actual size %lld", + path, (unsigned long long int) expected_size, + (unsigned long long int) st.st_size); +} + +/* Rename tests where the target does not exist. */ +static void +rename_without_existing_target (unsigned int flags) +{ + delete_all_files (); + support_write_file_string (old_path, ""); + TEST_COMPARE (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path, flags), 0); + TEST_VERIFY (!file_exists (old_path)); + TEST_VERIFY (file_exists (new_path)); + + delete_all_files (); + support_write_file_string (old_path, ""); + TEST_COMPARE (renameat2 (directory_fd, "old", AT_FDCWD, new_path, flags), 0); + TEST_VERIFY (!file_exists (old_path)); + TEST_VERIFY (file_exists (new_path)); + + delete_all_files (); + support_write_file_string (old_path, ""); + TEST_COMPARE (renameat2 (directory_fd, "old", subdirectory_fd, "file", 0), + 0); + TEST_VERIFY (!file_exists (old_path)); + TEST_VERIFY (file_exists (subdir_path)); +} + +static int +do_test (void) +{ + /* Tests with zero flags argument. These are expected to succeed + because this renameat2 variant can be implemented with + renameat. */ + rename_without_existing_target (0); + + /* renameat2 without flags replaces an existing destination. */ + delete_all_files (); + support_write_file_string (old_path, "123"); + support_write_file_string (new_path, "1234"); + TEST_COMPARE (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path, 0), 0); + TEST_VERIFY (!file_exists (old_path)); + check_size (new_path, 3); + + /* Now we need to check for kernel support of renameat2 with + flags. */ + delete_all_files (); + support_write_file_string (old_path, ""); + if (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path, RENAME_NOREPLACE) + != 0) + { + if (errno == EINVAL) + puts ("warning: no support for renameat2 with flags"); + else + FAIL_EXIT1 ("renameat2 probe failed: %m"); + } + else + { + /* We have full renameat2 support. */ + rename_without_existing_target (RENAME_NOREPLACE); + + /* Now test RENAME_NOREPLACE with an existing target. */ + delete_all_files (); + support_write_file_string (old_path, "123"); + support_write_file_string (new_path, "1234"); + TEST_COMPARE (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path, + RENAME_NOREPLACE), -1); + TEST_COMPARE (errno, EEXIST); + check_size (old_path, 3); + check_size (new_path, 4); + + delete_all_files (); + support_write_file_string (old_path, "123"); + support_write_file_string (new_path, "1234"); + TEST_COMPARE (renameat2 (directory_fd, "old", AT_FDCWD, new_path, + RENAME_NOREPLACE), -1); + TEST_COMPARE (errno, EEXIST); + check_size (old_path, 3); + check_size (new_path, 4); + + delete_all_files (); + support_write_file_string (old_path, "123"); + support_write_file_string (subdir_path, "1234"); + TEST_COMPARE (renameat2 (directory_fd, "old", subdirectory_fd, "file", + RENAME_NOREPLACE), -1); + TEST_COMPARE (errno, EEXIST); + check_size (old_path, 3); + check_size (subdir_path, 4); + + /* The flag combination of RENAME_NOREPLACE and RENAME_EXCHANGE + is invalid. */ + TEST_COMPARE (renameat2 (directory_fd, "ignored", + subdirectory_fd, "ignored", + RENAME_NOREPLACE | RENAME_EXCHANGE), -1); + TEST_COMPARE (errno, EINVAL); + } + + /* Create all the pathnames to avoid warnings from the test + harness. */ + support_write_file_string (old_path, ""); + support_write_file_string (new_path, ""); + support_write_file_string (subdir_path, ""); + + free (directory); + free (subdirectory); + free (old_path); + free (new_path); + free (subdir_path); + + xclose (directory_fd); + xclose (subdirectory_fd); + + return 0; +} + +#define PREPARE prepare +#include <support/test-driver.c> diff --git a/stdio-common/tst-scanf-round.c b/stdio-common/tst-scanf-round.c new file mode 100644 index 0000000000..a2fb620abf --- /dev/null +++ b/stdio-common/tst-scanf-round.c @@ -0,0 +1,51 @@ +/* Test for correct rounding of negative floating-point numbers by scanf + (bug 23280). + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <stdio.h> +#include <stdlib.h> +#include <support/check.h> + +static int +do_test (void) +{ +#ifdef FE_DOWNWARD + if (fesetround (FE_DOWNWARD) == 0) + { + double a = strtod ("-0.1", NULL); + double b = 0; + int r = sscanf ("-0.1", "%lf", &b); + TEST_VERIFY (r == 1); + TEST_VERIFY (a == b); + } +#endif +#ifdef FE_UPWARD + if (fesetround (FE_UPWARD) == 0) + { + double a = strtod ("-0.1", NULL); + double b = 0; + int r = sscanf ("-0.1", "%lf", &b); + TEST_VERIFY (r == 1); + TEST_VERIFY (a == b); + } +#endif + return 0; +} + +#include <support/test-driver.c> diff --git a/stdio-common/tst-sprintf.c b/stdio-common/tst-sprintf.c index d5284b9697..cbd35447a9 100644 --- a/stdio-common/tst-sprintf.c +++ b/stdio-common/tst-sprintf.c @@ -2,7 +2,7 @@ #include <stdlib.h> #include <locale.h> #include <string.h> -#include <libc-internal.h> +#include <libc-diag.h> static int diff --git a/stdio-common/tst-sprintf3.c b/stdio-common/tst-sprintf3.c index cffd1b69d0..deaee93803 100644 --- a/stdio-common/tst-sprintf3.c +++ b/stdio-common/tst-sprintf3.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2016 Free Software Foundation, Inc. +/* Copyright (C) 2012-2018 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 @@ -38,11 +38,11 @@ do_test (void) # define COMPARE_LDBL(u, v) ((u).l == (v).l) #endif -#define TEST(val) \ +#define TEST_N(val, n) \ do \ { \ u.l = (val); \ - snprintf (buf, sizeof buf, "%.30LgL", u.l); \ + snprintf (buf, sizeof buf, "%." #n "LgL", u.l); \ if (strcmp (buf, #val) != 0) \ { \ printf ("Error on line %d: %s != %s\n", __LINE__, buf, #val); \ @@ -50,19 +50,25 @@ do_test (void) } \ if (sscanf (#val, "%Lg", &v.l) != 1 || !COMPARE_LDBL (u, v)) \ { \ - printf ("Error sscanf on line %d: %.30Lg != %.30Lg\n", __LINE__, \ - u.l, v.l); \ + printf ("Error sscanf on line %d: %." #n "Lg != %." #n "Lg\n", \ + __LINE__, u.l, v.l); \ result = 1; \ } \ /* printf ("%s %Lg %016Lx %016Lx\n", #val, u.l, u.x[0], u.x[1]); */ \ } \ while (0) +#define TEST(val) TEST_N (val,30) + #if LDBL_MANT_DIG >= 106 # if LDBL_MANT_DIG == 106 TEST (2.22507385850719347803989925739e-308L); TEST (2.22507385850719397210554509863e-308L); TEST (2.22507385850720088902458687609e-308L); + + /* Verify precision is not lost for long doubles + of the form +1.pN,-1.pM. */ + TEST_N (3.32306998946228968225951765070082e+35L, 34); # endif TEST (2.22507385850720138309023271733e-308L); TEST (2.22507385850720187715587855858e-308L); diff --git a/stdio-common/tst-sscanf.c b/stdio-common/tst-sscanf.c index f52cc9e07e..87a6c0defa 100644 --- a/stdio-common/tst-sscanf.c +++ b/stdio-common/tst-sscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2016 Free Software Foundation, Inc. +/* Copyright (C) 2000-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2000. @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <array_length.h> #include <stdlib.h> #include <stdio.h> #include <locale.h> @@ -184,7 +185,7 @@ do_test (void) break; } - for (i = 0; i < sizeof (int_tests) / sizeof (int_tests[0]); ++i) + for (i = 0; i < array_length (int_tests); ++i) { long dummy; int ret; @@ -198,7 +199,7 @@ do_test (void) } } - for (i = 0; i < sizeof (double_tests) / sizeof (double_tests[0]); ++i) + for (i = 0; i < array_length (double_tests); ++i) { double dummy; int ret; @@ -212,7 +213,7 @@ do_test (void) } } - for (i = 0; i < sizeof (double_tests2) / sizeof (double_tests2[0]); ++i) + for (i = 0; i < array_length (double_tests2); ++i) { double dummy; int ret; diff --git a/stdio-common/tst-swprintf.c b/stdio-common/tst-swprintf.c index ce62c6bf68..07194eb67d 100644 --- a/stdio-common/tst-swprintf.c +++ b/stdio-common/tst-swprintf.c @@ -1,3 +1,4 @@ +#include <array_length.h> #include <locale.h> #include <stdio.h> #include <stdlib.h> @@ -16,7 +17,6 @@ static int do_test (void) { wchar_t buf[1000]; -#define nbuf (sizeof (buf) / sizeof (buf[0])) int result = 0; ssize_t n; @@ -27,7 +27,7 @@ do_test (void) } #define CHECK(fmt, nexp, exp) \ - n = swprintf (buf, nbuf, fmt, input); \ + n = swprintf (buf, array_length (buf), fmt, input); \ if (n != nexp) \ { \ printf ("swprintf (.., .., L\"%ls\", \"%ls\") return %d, not %d\n", \ diff --git a/stdio-common/tst-tmpnam.c b/stdio-common/tst-tmpnam.c index e3dc0776cd..f82576ad3e 100644 --- a/stdio-common/tst-tmpnam.c +++ b/stdio-common/tst-tmpnam.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998-2016 Free Software Foundation, Inc. +/* Copyright (C) 1998-2018 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 diff --git a/stdio-common/tst-unbputc.sh b/stdio-common/tst-unbputc.sh index 8156400730..90a810ccee 100755 --- a/stdio-common/tst-unbputc.sh +++ b/stdio-common/tst-unbputc.sh @@ -1,6 +1,6 @@ #!/bin/sh # Testing the stdio implementation -# Copyright (C) 2000-2016 Free Software Foundation, Inc. +# Copyright (C) 2000-2018 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 diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c index 44cf6a6bf6..1344b2b591 100644 --- a/stdio-common/tst-ungetc.c +++ b/stdio-common/tst-ungetc.c @@ -1,6 +1,7 @@ /* Test for ungetc bugs. */ #include <stdio.h> +#include <stdlib.h> #include <unistd.h> #undef assert @@ -15,13 +16,19 @@ int main (int argc, char *argv[]) { - char *name; + char name[] = "/tmp/tst-ungetc.XXXXXX"; FILE *fp = NULL; int retval = 0; int c; char buffer[64]; - name = tmpnam (NULL); + int fd = mkstemp (name); + if (fd == -1) + { + printf ("mkstemp failed: %m\n"); + return 1; + } + close (fd); fp = fopen (name, "w"); assert (fp != NULL) fputs ("bla", fp); diff --git a/stdio-common/tst-unlockedio.c b/stdio-common/tst-unlockedio.c index 4e47e14f5b..4837fd2e4b 100644 --- a/stdio-common/tst-unlockedio.c +++ b/stdio-common/tst-unlockedio.c @@ -1,5 +1,5 @@ /* Test for some *_unlocked stdio interfaces. - Copyright (C) 2004-2016 Free Software Foundation, Inc. + Copyright (C) 2004-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. @@ -20,7 +20,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <libc-internal.h> +#include <libc-diag.h> int fd; static void do_prepare (void); diff --git a/stdio-common/tst-vfprintf-mbs-prec.c b/stdio-common/tst-vfprintf-mbs-prec.c new file mode 100644 index 0000000000..7f95e6cceb --- /dev/null +++ b/stdio-common/tst-vfprintf-mbs-prec.c @@ -0,0 +1,543 @@ +/* Test for wchar_t/multi-byte conversion and precision in vfprintf. + Copyright (C) 2017-2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <locale.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <support/check.h> +#include <support/test-driver.h> +#include <wchar.h> + +#define DYNARRAY_STRUCT str +#define DYNARRAY_ELEMENT char +#define DYNARRAY_PREFIX str_ +#include <malloc/dynarray-skeleton.c> + +#define DYNARRAY_STRUCT wstr +#define DYNARRAY_ELEMENT wchar_t +#define DYNARRAY_PREFIX wstr_ +#include <malloc/dynarray-skeleton.c> + +#define DYNARRAY_STRUCT len +#define DYNARRAY_ELEMENT size_t +#define DYNARRAY_PREFIX len_ +#include <malloc/dynarray-skeleton.c> + +/* This should be larger than the internal buffer in vfprintf. The + constant needs to be kept in sync with the format strings in + test_mbs_long and test_wide_long. */ +enum { WIDE_STRING_LENGTH = 1000 }; + +/* Creates two large, random strings used for truncation testing. + After the call, *MBS will be encoded in UTF-8, and *WIDE will + contain the same string in the internal UCS-32 encoding. Both + strings are null-terminated. The array *LENGTH counts the number + of multi-byte characters for each prefix string of *WIDE: The first + N wide characters of *WIDE correspond the first (*LENGTH)[N] bytes + of *MBS. The caller should deallocate all three arrays using + free. */ +static void +make_random_string (char **mbs, wchar_t **wide, size_t **length) +{ + struct str str; + str_init (&str); + struct wstr wstr; + wstr_init (&wstr); + struct len len; + len_init (&len); + + for (int i = 0; i < WIDE_STRING_LENGTH; ++i) + { + len_add (&len, str_size (&str)); + /* Cover some multi-byte UTF-8 sequences. Avoid the null + character. */ + uint32_t ch = 1 + (rand () % 521); + wstr_add (&wstr, ch); + + /* Limited UTF-8 conversion. */ + if (ch <= 127) + str_add (&str, ch); + else + { + /* We only implement two-byte sequences. */ + uint32_t first = ch >> 6; + TEST_VERIFY (first < 32); + str_add (&str, 0xC0 | first); + str_add (&str, 0x80 | (ch & 0x3f)); + } + } + len_add (&len, str_size (&str)); + wstr_add (&wstr, L'\0'); + str_add (&str, '\0'); + + *mbs = str_finalize (&str, NULL); + TEST_VERIFY_EXIT (*mbs != NULL); + *wide = wstr_finalize (&wstr, NULL); + TEST_VERIFY_EXIT (*wide != NULL); + *length = len_finalize (&len, NULL); + TEST_VERIFY_EXIT (*length != NULL); +} + +/* snprintf tests (multi-byte result). */ +static void +test_mbs_result (void) +{ + char buf[200]; + + /* ASCII wide string. */ + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%ls", L"xyz") == 3); + TEST_VERIFY (strcmp (buf, "xyz") == 0); + + /* Unicode wide string. */ + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + + /* Varying precisions. */ + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%.1ls", L"x\u00DFz") == 1); + TEST_VERIFY (strcmp (buf, "x") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%.2ls", L"x\u00DFz") == 1); + TEST_VERIFY (strcmp (buf, "x") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%.3ls", L"x\u00DFz") == 3); + TEST_VERIFY (strcmp (buf, "x\xC3\x9F") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%.4ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%.5ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + + /* Varying precisions with width 2, right-justified. */ + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%2.1ls", L"x\u00DFz") == 2); + TEST_VERIFY (strcmp (buf, " x") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%2.2ls", L"x\u00DFz") == 2); + TEST_VERIFY (strcmp (buf, " x") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%2.3ls", L"x\u00DFz") == 3); + TEST_VERIFY (strcmp (buf, "x\xC3\x9F") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%2.4ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%2.5ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + + /* Varying precisions with width 2, left-justified. */ + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-2.1ls", L"x\u00DFz") == 2); + TEST_VERIFY (strcmp (buf, "x ") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-2.2ls", L"x\u00DFz") == 2); + TEST_VERIFY (strcmp (buf, "x ") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-2.3ls", L"x\u00DFz") == 3); + TEST_VERIFY (strcmp (buf, "x\xC3\x9F") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-2.4ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-2.5ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + + /* Varying precisions with width 3, right-justified. */ + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%3.1ls", L"x\u00DFz") == 3); + TEST_VERIFY (strcmp (buf, " x") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%3.2ls", L"x\u00DFz") == 3); + TEST_VERIFY (strcmp (buf, " x") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%3.3ls", L"x\u00DFz") == 3); + TEST_VERIFY (strcmp (buf, "x\xC3\x9F") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%3.4ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%3.5ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + + /* Varying precisions with width 3, left-justified. */ + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-3.1ls", L"x\u00DFz") == 3); + TEST_VERIFY (strcmp (buf, "x ") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-3.2ls", L"x\u00DFz") == 3); + TEST_VERIFY (strcmp (buf, "x ") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-3.3ls", L"x\u00DFz") == 3); + TEST_VERIFY (strcmp (buf, "x\xC3\x9F") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-3.4ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-3.5ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + + /* Varying precisions with width 4, right-justified. */ + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%4.1ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, " x") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%4.2ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, " x") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%4.3ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, " x\xC3\x9F") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%4.4ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%4.5ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + + /* Varying precisions with width 4, left-justified. */ + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-4.1ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x ") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-4.2ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x ") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-4.3ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9F ") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-4.4ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); + memset (buf, '@', sizeof (buf)); + TEST_VERIFY (snprintf (buf, sizeof (buf), "%-4.5ls", L"x\u00DFz") == 4); + TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0); +} + +/* swprintf tests (wide string result). */ +static void +test_wide_result (void) +{ + enum { size = 20 }; + wchar_t buf[20]; + + /* ASCII wide string. */ + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%s", "xyz") == 3); + TEST_VERIFY (wcscmp (buf, L"xyz") == 0); + + /* Unicode wide string. */ + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + + /* Varying precisions. */ + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%.1s", "x\xC3\x9Fz") == 1); + TEST_VERIFY (wcscmp (buf, L"x") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%.2s", "x\xC3\x9Fz") == 2); + TEST_VERIFY (wcscmp (buf, L"x\u00DF") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%.3s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%.4s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + + /* Varying precisions with width 2, right-justified. */ + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%2.1s", "x\xC3\x9Fz") == 2); + TEST_VERIFY (wcscmp (buf, L" x") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%2.2s", "x\xC3\x9Fz") == 2); + TEST_VERIFY (wcscmp (buf, L"x\u00DF") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%2.3s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%2.4s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + + /* Varying precisions with width 2, left-justified. */ + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-2.1s", "x\xC3\x9Fz") == 2); + TEST_VERIFY (wcscmp (buf, L"x ") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-2.2s", "x\xC3\x9Fz") == 2); + TEST_VERIFY (wcscmp (buf, L"x\u00DF") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-2.3s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-2.4s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + + /* Varying precisions with width 3, right-justified. */ + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%3.1s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L" x") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%3.2s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L" x\u00DF") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%3.3s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%3.4s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + + /* Varying precisions with width 3, left-justified. */ + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-3.1s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x ") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-3.2s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DF ") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-3.3s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-3.4s", "x\xC3\x9Fz") == 3); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0); + + /* Varying precisions with width 4, right-justified. */ + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%4.1s", "x\xC3\x9Fz") == 4); + TEST_VERIFY (wcscmp (buf, L" x") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%4.2s", "x\xC3\x9Fz") == 4); + TEST_VERIFY (wcscmp (buf, L" x\u00DF") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%4.3s", "x\xC3\x9Fz") == 4); + TEST_VERIFY (wcscmp (buf, L" x\u00DFz") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%4.4s", "x\xC3\x9Fz") == 4); + TEST_VERIFY (wcscmp (buf, L" x\u00DFz") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%4.5s", "x\xC3\x9Fz") == 4); + TEST_VERIFY (wcscmp (buf, L" x\u00DFz") == 0); + + /* Varying precisions with width 4, left-justified. */ + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-4.1s", "x\xC3\x9Fz") == 4); + TEST_VERIFY (wcscmp (buf, L"x ") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-4.2s", "x\xC3\x9Fz") == 4); + TEST_VERIFY (wcscmp (buf, L"x\u00DF ") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-4.3s", "x\xC3\x9Fz") == 4); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz ") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-4.4s", "x\xC3\x9Fz") == 4); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz ") == 0); + wmemset (buf, '@', size); + TEST_VERIFY (swprintf (buf, size, L"%-4.5s", "x\xC3\x9Fz") == 4); + TEST_VERIFY (wcscmp (buf, L"x\u00DFz ") == 0); +} + +/* Test with long strings and multi-byte result. */ +static void +test_mbs_long (const char *mbs, const wchar_t *wide, const size_t *length) +{ + char buf[4000]; + _Static_assert (sizeof (buf) > 3 * WIDE_STRING_LENGTH, + "buffer size consistent with string length"); + const char *suffix = "||TERM"; + TEST_VERIFY_EXIT (sizeof (buf) + > length[WIDE_STRING_LENGTH] + strlen (suffix)); + + /* Test formatting of the entire string. */ + { + int ret = snprintf (buf, sizeof (buf), "%ls%s", wide, suffix); + TEST_VERIFY (ret == length[WIDE_STRING_LENGTH] + strlen (suffix)); + TEST_VERIFY (memcmp (buf, mbs, length[WIDE_STRING_LENGTH]) == 0); + TEST_VERIFY (strcmp (buf + length[WIDE_STRING_LENGTH], suffix) == 0); + + /* Left-justified string, printed in full. */ + ret = snprintf (buf, sizeof (buf), "%-3500ls%s", wide, suffix); + TEST_VERIFY (ret == 3500 + strlen (suffix)); + TEST_VERIFY (memcmp (buf, mbs, length[WIDE_STRING_LENGTH]) == 0); + for (size_t i = length[WIDE_STRING_LENGTH]; i < 3500; ++i) + TEST_VERIFY (buf[i] == ' '); + TEST_VERIFY (strcmp (buf + 3500, suffix) == 0); + + /* Right-justified string, printed in full. */ + ret = snprintf (buf, sizeof (buf), "%3500ls%s", wide, suffix); + TEST_VERIFY (ret == 3500 + strlen (suffix)); + size_t padding = 3500 - length[WIDE_STRING_LENGTH]; + for (size_t i = 0; i < padding; ++i) + TEST_VERIFY (buf[i] == ' '); + TEST_VERIFY (memcmp (buf + padding, mbs, length[WIDE_STRING_LENGTH]) == 0); + TEST_VERIFY (strcmp (buf + 3500, suffix) == 0); + } + + size_t wide_characters_converted = 0; + for (int mbs_len = 0; mbs_len <= length[WIDE_STRING_LENGTH] + 1; + ++mbs_len) + { + if (wide_characters_converted < WIDE_STRING_LENGTH + && mbs_len >= length[wide_characters_converted + 1]) + /* The requested prefix length contains room for another wide + character. */ + ++wide_characters_converted; + if (test_verbose > 0) + printf ("info: %s: mbs_len=%d wide_chars_converted=%zu length=%zu\n", + __func__, mbs_len, wide_characters_converted, + length[wide_characters_converted]); + TEST_VERIFY (length[wide_characters_converted] <= mbs_len); + TEST_VERIFY (wide_characters_converted == 0 + || length[wide_characters_converted - 1] < mbs_len); + + int ret = snprintf (buf, sizeof (buf), "%.*ls%s", mbs_len, wide, suffix); + TEST_VERIFY (ret == length[wide_characters_converted] + strlen (suffix)); + TEST_VERIFY (memcmp (buf, mbs, length[wide_characters_converted]) == 0); + TEST_VERIFY (strcmp (buf + length[wide_characters_converted], + suffix) == 0); + + /* Left-justified string, printed in full. */ + if (test_verbose) + printf ("info: %s: left-justified\n", __func__); + ret = snprintf (buf, sizeof (buf), "%-3500.*ls%s", + mbs_len, wide, suffix); + TEST_VERIFY (ret == 3500 + strlen (suffix)); + TEST_VERIFY (memcmp (buf, mbs, length[wide_characters_converted]) == 0); + for (size_t i = length[wide_characters_converted]; i < 3500; ++i) + TEST_VERIFY (buf[i] == ' '); + TEST_VERIFY (strcmp (buf + 3500, suffix) == 0); + + /* Right-justified string, printed in full. */ + if (test_verbose) + printf ("info: %s: right-justified\n", __func__); + ret = snprintf (buf, sizeof (buf), "%3500.*ls%s", mbs_len, wide, suffix); + TEST_VERIFY (ret == 3500 + strlen (suffix)); + size_t padding = 3500 - length[wide_characters_converted]; + for (size_t i = 0; i < padding; ++i) + TEST_VERIFY (buf[i] == ' '); + TEST_VERIFY (memcmp (buf + padding, mbs, + length[wide_characters_converted]) == 0); + TEST_VERIFY (strcmp (buf + 3500, suffix) == 0); + } +} + +/* Test with long strings and wide string result. */ +static void +test_wide_long (const char *mbs, const wchar_t *wide, const size_t *length) +{ + wchar_t buf[2000]; + _Static_assert (sizeof (buf) > sizeof (wchar_t) * WIDE_STRING_LENGTH, + "buffer size consistent with string length"); + const wchar_t *suffix = L"||TERM"; + TEST_VERIFY_EXIT (sizeof (buf) + > length[WIDE_STRING_LENGTH] + wcslen (suffix)); + + /* Test formatting of the entire string. */ + { + int ret = swprintf (buf, sizeof (buf), L"%s%ls", mbs, suffix); + TEST_VERIFY (ret == WIDE_STRING_LENGTH + wcslen (suffix)); + TEST_VERIFY (wmemcmp (buf, wide, WIDE_STRING_LENGTH) == 0); + TEST_VERIFY (wcscmp (buf + WIDE_STRING_LENGTH, suffix) == 0); + + /* Left-justified string, printed in full. */ + ret = swprintf (buf, sizeof (buf), L"%-1500s%ls", mbs, suffix); + TEST_VERIFY (ret == 1500 + wcslen (suffix)); + TEST_VERIFY (wmemcmp (buf, wide, WIDE_STRING_LENGTH) == 0); + for (size_t i = WIDE_STRING_LENGTH; i < 1500; ++i) + TEST_VERIFY (buf[i] == L' '); + TEST_VERIFY (wcscmp (buf + 1500, suffix) == 0); + + /* Right-justified string, printed in full. */ + ret = swprintf (buf, sizeof (buf), L"%1500s%ls", mbs, suffix); + TEST_VERIFY (ret == 1500 + wcslen (suffix)); + size_t padding = 1500 - WIDE_STRING_LENGTH; + for (size_t i = 0; i < padding; ++i) + TEST_VERIFY (buf[i] == ' '); + TEST_VERIFY (wmemcmp (buf + padding, wide, WIDE_STRING_LENGTH) == 0); + TEST_VERIFY (wcscmp (buf + 1500, suffix) == 0); + } + + for (int wide_len = 0; wide_len <= WIDE_STRING_LENGTH + 1; ++wide_len) + { + size_t actual_wide_len; + if (wide_len < WIDE_STRING_LENGTH) + actual_wide_len = wide_len; + else + actual_wide_len = WIDE_STRING_LENGTH; + if (test_verbose > 0) + printf ("info: %s: wide_len=%d actual_wide_len=%zu\n", + __func__, wide_len, actual_wide_len); + + int ret = swprintf (buf, sizeof (buf), L"%.*s%ls", + wide_len, mbs, suffix); + TEST_VERIFY (ret == actual_wide_len + wcslen (suffix)); + TEST_VERIFY (wmemcmp (buf, wide, actual_wide_len) == 0); + TEST_VERIFY (wcscmp (buf + actual_wide_len, suffix) == 0); + + /* Left-justified string, printed in full. */ + ret = swprintf (buf, sizeof (buf), L"%-1500.*s%ls", + wide_len, mbs, suffix); + TEST_VERIFY (ret == 1500 + wcslen (suffix)); + TEST_VERIFY (wmemcmp (buf, wide, actual_wide_len) == 0); + for (size_t i = actual_wide_len; i < 1500; ++i) + TEST_VERIFY (buf[i] == L' '); + TEST_VERIFY (wcscmp (buf + 1500, suffix) == 0); + + /* Right-justified string, printed in full. */ + ret = swprintf (buf, sizeof (buf), L"%1500.*s%ls", + wide_len, mbs, suffix); + TEST_VERIFY (ret == 1500 + wcslen (suffix)); + size_t padding = 1500 - actual_wide_len; + for (size_t i = 0; i < padding; ++i) + TEST_VERIFY (buf[i] == L' '); + TEST_VERIFY (wmemcmp (buf + padding, wide, actual_wide_len) == 0); + TEST_VERIFY (wcscmp (buf + 1500, suffix) == 0); + } +} + +static int +do_test (void) +{ + /* This test only covers UTF-8 as a multi-byte character set. A + locale with a multi-byte character set with shift state would be + a relevant test target as well, but glibc currently does not ship + such a locale. */ + TEST_VERIFY (setlocale (LC_CTYPE, "de_DE.UTF-8") != NULL); + + test_mbs_result (); + test_wide_result (); + + char *mbs; + wchar_t *wide; + size_t *length; + make_random_string (&mbs, &wide, &length); + TEST_VERIFY (strlen (mbs) == length[WIDE_STRING_LENGTH]); + if (test_verbose > 0) + printf ("info: long multi-byte string contains %zu characters\n", + length[WIDE_STRING_LENGTH]); + test_mbs_long (mbs, wide, length); + test_wide_long (mbs, wide, length); + free (mbs); + free (wide); + free (length); + + return 0; +} + +#include <support/test-driver.c> diff --git a/stdio-common/tst-vfprintf-user-type.c b/stdio-common/tst-vfprintf-user-type.c new file mode 100644 index 0000000000..1ee86312d8 --- /dev/null +++ b/stdio-common/tst-vfprintf-user-type.c @@ -0,0 +1,220 @@ +/* Test for user-defined types in vfprintf. + Copyright (C) 2017-2018 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 + <http://www.gnu.org/licenses/>. */ + +/* This test contains a printf format specifier, %P, with a custom + type which is a long/double pair. If a precision is specified, + this indicates the number of such pairs which constitute the + argument. */ + +#include <locale.h> +#include <printf.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/support.h> +#include <support/test-driver.h> +#include <wchar.h> + +/* Initialized by do_test using register_printf_type. */ +static int user_type; + +struct two_argument +{ + long i; + double d; +}; + +static void +my_va_arg_function (void *mem, va_list *ap) +{ + if (test_verbose > 0) + printf ("info: %s (%p) called\n", __func__, mem); + + struct two_argument *pair = mem; + pair->i = va_arg (*ap, long); + pair->d = va_arg (*ap, double); +} + +static int +my_printf_function (FILE *fp, const struct printf_info *info, + const void *const *args) +{ + if (test_verbose > 0) + printf ("info: %s (%p, %p, {%p}@%p) called for %%%lc (prec %d)\n", + __func__, fp, info, args[0], args, (wint_t) info->spec, + info->prec); + + TEST_VERIFY (info->spec == 'P'); + size_t nargs; + int printed; + if (info->prec >= 0) + { + if (fputc ('{', fp) < 0) + return -1; + nargs = info->prec; + printed = 1; + } + else + { + nargs = 1; + printed = 0; + } + + for (size_t i = 0; i < nargs; ++i) + { + if (i != 0) + { + if (fputc (',', fp) < 0) + return -1; + ++printed; + } + + /* NB: Triple pointer indirection. ARGS is an array of void *, + and those pointers point to a pointer to the memory area + supplied to my_va_arg_function. */ + struct two_argument *pair = *(void **) args[i]; + int ret = fprintf (fp, "(%ld, %f)", pair->i, pair->d); + if (ret < 0) + return -1; + printed += ret; + } + if (info->prec >= 0) + { + if (fputc ('}', fp) < 0) + return -1; + ++printed; + } + return printed; +} + +static int +my_arginfo_function (const struct printf_info *info, + size_t n, int *argtypes, int *size) +{ + /* Avoid recursion. */ + if (info->spec != 'P') + return -1; + if (test_verbose > 0) + printf ("info: %s (%p, %zu, %p, %p) called for %%%lc (prec %d)\n", + __func__, info, n, argtypes, size, (wint_t) info->spec, + info->prec); + + TEST_VERIFY_EXIT (n >= 1); + size_t nargs; + if (info->prec >= 0) + nargs = info->prec; + else + nargs = 1; + + size_t to_fill = nargs; + if (to_fill > n) + to_fill = n; + for (size_t i = 0; i < to_fill; ++i) + { + argtypes[i] = user_type; + size[i] = sizeof (struct two_argument); + } + if (test_verbose > 0) + printf ("info: %s return value: %zu\n", __func__, nargs); + return nargs; +} + +static int +do_test (void) +{ + user_type = register_printf_type (my_va_arg_function); + if (test_verbose > 0) + printf ("info: allocated user type: %d\n", user_type); + TEST_VERIFY_EXIT (user_type >= PA_LAST); + TEST_VERIFY_EXIT (register_printf_specifier + ('P', my_printf_function, my_arginfo_function) >= 0); + + /* Alias declaration for asprintf, to avoid the format string + attribute and the associated warning. */ + extern int asprintf_alias (char **, const char *, ...) __asm__ ("asprintf"); + TEST_VERIFY (asprintf_alias == asprintf); + char *str = NULL; + TEST_VERIFY (asprintf_alias (&str, "[[%P]]", 123L, 456.0) >= 0); + if (test_verbose > 0) + printf ("info: %s\n", str); + TEST_VERIFY (strcmp (str, "[[(123, 456.000000)]]") == 0); + free (str); + + str = NULL; + TEST_VERIFY (asprintf_alias (&str, "[[%1$P %1$P]]", 123L, 457.0) >= 0); + if (test_verbose > 0) + printf ("info: %s\n", str); + TEST_VERIFY (strcmp (str, "[[(123, 457.000000) (123, 457.000000)]]") == 0); + free (str); + + str = NULL; + TEST_VERIFY (asprintf_alias (&str, "[[%.1P]]", 1L, 2.0) >= 0); + if (test_verbose > 0) + printf ("info: %s\n", str); + TEST_VERIFY (strcmp (str, "[[{(1, 2.000000)}]]") == 0); + free (str); + + str = NULL; + TEST_VERIFY (asprintf_alias (&str, "[[%.2P]]", 1L, 2.0, 3L, 4.0) >= 0); + if (test_verbose > 0) + printf ("info: %s\n", str); + TEST_VERIFY (strcmp (str, "[[{(1, 2.000000),(3, 4.000000)}]]") == 0); + free (str); + + str = NULL; + TEST_VERIFY (asprintf_alias + (&str, "[[%.2P | %.3P]]", + /* argument 1: */ 1L, 2.0, 3L, 4.0, + /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0) + >= 0); + if (test_verbose > 0) + printf ("info: %s\n", str); + TEST_VERIFY (strcmp (str, + "[[" + "{(1, 2.000000),(3, 4.000000)}" + " | " + "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}" + "]]") == 0); + free (str); + + /* The following subtest fails due to bug 21534. */ +#if 0 + str = NULL; + TEST_VERIFY (asprintf_alias + (&str, "[[%1$.2P | %2$.3P | %1$.2P]]", + /* argument 1: */ 1L, 2.0, 3L, 4.0, + /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0) + >= 0); + if (test_verbose > 0) + printf ("info: %s\n", str); + TEST_VERIFY (strcmp (str, + "[[" + "{(1, 2.000000),(3, 4.000000)}" + " | " + "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}" + " | " + "{(1, 2.000000),(3, 4.000000)}" + "]]") == 0); + free (str); +#endif + + return 0; +} + +#include <support/test-driver.c> diff --git a/stdio-common/tst-vfprintf-width-prec.c b/stdio-common/tst-vfprintf-width-prec.c new file mode 100644 index 0000000000..fa61f5c22c --- /dev/null +++ b/stdio-common/tst-vfprintf-width-prec.c @@ -0,0 +1,108 @@ +/* Test for memory leak with large width and precision. + Copyright (C) 1991-2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <mcheck.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/resource.h> +#include <wchar.h> + +static int +do_test (void) +{ + mtrace (); + + int ret; + { + char *result; + ret = asprintf (&result, "%133000.133001x", 17); + if (ret < 0) + { + printf ("error: asprintf: %m\n"); + return 1; + } + free (result); + } + { + wchar_t *result = calloc (ret + 1, sizeof (wchar_t)); + if (result == NULL) + { + printf ("error: calloc (%d, %zu): %m", ret + 1, sizeof (wchar_t)); + return 1; + } + + ret = swprintf (result, ret + 1, L"%133000.133001x", 17); + if (ret < 0) + { + printf ("error: swprintf: %d (%m)\n", ret); + return 1; + } + free (result); + } + + /* Limit the size of the process, so that the second allocation will + fail. */ + { + struct rlimit limit; + if (getrlimit (RLIMIT_AS, &limit) != 0) + { + printf ("getrlimit (RLIMIT_AS) failed: %m\n"); + return 1; + } + long target = 200 * 1024 * 1024; + if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target) + { + limit.rlim_cur = target; + if (setrlimit (RLIMIT_AS, &limit) != 0) + { + printf ("setrlimit (RLIMIT_AS) failed: %m\n"); + return 1; + } + } + } + + { + char *result; + ret = asprintf (&result, "%133000.999999999x", 17); + if (ret >= 0) + { + printf ("error: asprintf: incorrect result %d\n", ret); + return 1; + } + } + { + wchar_t result[100]; + if (result == NULL) + { + printf ("error: calloc (%d, %zu): %m", ret + 1, sizeof (wchar_t)); + return 1; + } + + ret = swprintf (result, 100, L"%133000.999999999x", 17); + if (ret >= 0) + { + printf ("error: swprintf: incorrect result %d\n", ret); + return 1; + } + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdio-common/tstdiomisc.c b/stdio-common/tstdiomisc.c index 5548a71e52..c2fc73deb1 100644 --- a/stdio-common/tstdiomisc.c +++ b/stdio-common/tstdiomisc.c @@ -1,9 +1,10 @@ +#include <array_length.h> #include <float.h> #include <math.h> #include <stdio.h> #include <string.h> #include <wchar.h> -#include <libc-internal.h> +#include <libc-diag.h> static int t1 (void) @@ -66,8 +67,7 @@ t3 (void) retval = sprintf (buf, "%p", (char *) NULL); result |= retval != 5 || strcmp (buf, "(nil)") != 0; - retval = swprintf (wbuf, sizeof (wbuf) / sizeof (wbuf[0]), - L"%p", (char *) NULL); + retval = swprintf (wbuf, array_length (wbuf), L"%p", (char *) NULL); result |= retval != 5 || wcscmp (wbuf, L"(nil)") != 0; return result; @@ -94,6 +94,14 @@ F (void) qnanval = NAN; + /* The %f and %F arguments are in fact constants, but GCC is + prevented from seeing this (volatile is used) so it cannot tell + that the output is not truncated. */ + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (7, 0) + DIAG_IGNORE_NEEDS_COMMENT (7.0, "-Wformat-truncation"); +#endif + snprintf (buf, sizeof buf, "%a %A %e %E %f %F %g %G", qnanval, qnanval, qnanval, qnanval, qnanval, qnanval, qnanval, qnanval); @@ -134,38 +142,38 @@ F (void) printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n", buf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", qnanval, qnanval, qnanval, qnanval, qnanval, qnanval, qnanval, qnanval); result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0; printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", -qnanval, -qnanval, -qnanval, -qnanval, -qnanval, -qnanval, -qnanval, -qnanval); result |= wcscmp (wbuf, L"-nan -NAN -nan -NAN -nan -NAN -nan -NAN") != 0; printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", snanval, snanval, snanval, snanval, snanval, snanval, snanval, snanval); result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0; printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", msnanval, msnanval, msnanval, msnanval, msnanval, msnanval, msnanval, msnanval); result |= wcscmp (wbuf, L"-nan -NAN -nan -NAN -nan -NAN -nan -NAN") != 0; printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", infval, infval, infval, infval, infval, infval, infval, infval); result |= wcscmp (wbuf, L"inf INF inf INF inf INF inf INF") != 0; printf ("expected L\"inf INF inf INF inf INF inf INF\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", -infval, -infval, -infval, -infval, -infval, -infval, -infval, -infval); result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0; @@ -215,14 +223,14 @@ F (void) printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n", buf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", lqnanval, lqnanval, lqnanval, lqnanval, lqnanval, lqnanval, lqnanval, lqnanval); result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0; printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", -lqnanval, -lqnanval, -lqnanval, -lqnanval, -lqnanval, -lqnanval, -lqnanval, -lqnanval); @@ -230,14 +238,14 @@ F (void) printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", lsnanval, lsnanval, lsnanval, lsnanval, lsnanval, lsnanval, lsnanval, lsnanval); result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0; printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", lmsnanval, lmsnanval, lmsnanval, lmsnanval, lmsnanval, lmsnanval, lmsnanval, lmsnanval); @@ -245,14 +253,14 @@ F (void) printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", linfval, linfval, linfval, linfval, linfval, linfval, linfval, linfval); result |= wcscmp (wbuf, L"inf INF inf INF inf INF inf INF") != 0; printf ("expected L\"inf INF inf INF inf INF inf INF\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", -linfval, -linfval, -linfval, -linfval, -linfval, -linfval, -linfval, -linfval); @@ -260,6 +268,8 @@ F (void) printf ("expected L\"-inf -INF -inf -INF -inf -INF -inf -INF\", got L\"%S\"\n", wbuf); + DIAG_POP_NEEDS_COMMENT; + return result; } diff --git a/stdio-common/tstgetln.c b/stdio-common/tstgetln.c index d52b2bce60..6960e68620 100644 --- a/stdio-common/tstgetln.c +++ b/stdio-common/tstgetln.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2016 Free Software Foundation, Inc. +/* Copyright (C) 1992-2018 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 @@ -16,8 +16,6 @@ <http://www.gnu.org/licenses/>. */ #include <stdio.h> -#undef ssize_t -#define ssize_t _IO_ssize_t int main (int argc, char *argv[]) diff --git a/stdio-common/tstscanf.c b/stdio-common/tstscanf.c index 767b4d6202..019a5c8a4d 100644 --- a/stdio-common/tstscanf.c +++ b/stdio-common/tstscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -15,6 +15,7 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <array_length.h> #ifdef BSD #include </usr/include/stdio.h> #else @@ -154,7 +155,7 @@ main (int argc, char **argv) { int count; - if (rounds++ >= sizeof (ok) / sizeof (ok[0])) + if (rounds++ >= array_length (ok)) { fputs ("test failed!\n", stdout); result = 1; diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 6829d4dc8e..ae412e4b84 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -15,6 +15,7 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <array_length.h> #include <ctype.h> #include <limits.h> #include <printf.h> @@ -38,13 +39,12 @@ Beside this it is also shared between the normal and wide character implementation as defined in ISO/IEC 9899:1990/Amendment 1:1995. */ - #include <libioP.h> -#define FILE _IO_FILE -#undef va_list -#define va_list _IO_va_list -#undef BUFSIZ -#define BUFSIZ _IO_BUFSIZ + +/* In some cases we need extra space for all the output which is not + counted in the width of the string. We assume 32 characters is + enough. */ +#define EXTSIZ 32 #define ARGCHECK(S, Format) \ do \ { \ @@ -58,11 +58,11 @@ } \ if (Format == NULL) \ { \ - MAYBE_SET_EINVAL; \ + __set_errno (EINVAL); \ return -1; \ } \ } while (0) -#define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED) +#define UNBUFFERED_P(S) ((S)->_flags & _IO_UNBUFFERED) #define done_add(val) \ do { \ @@ -92,7 +92,7 @@ typedef const char *THOUSANDS_SEP_T; do { \ if (width > 0) \ { \ - _IO_ssize_t written = _IO_padn (s, (Padchar), width); \ + ssize_t written = _IO_padn (s, (Padchar), width); \ if (__glibc_unlikely (written != width)) \ { \ done = -1; \ @@ -122,7 +122,7 @@ typedef wchar_t THOUSANDS_SEP_T; do { \ if (width > 0) \ { \ - _IO_ssize_t written = _IO_wpadn (s, (Padchar), width); \ + ssize_t written = _IO_wpadn (s, (Padchar), width); \ if (__glibc_unlikely (written != width)) \ { \ done = -1; \ @@ -201,7 +201,7 @@ typedef wchar_t THOUSANDS_SEP_T; static const CHAR_T null[] = L_("(null)"); /* Size of the work_buffer variable (in characters, not bytes. */ -enum { WORK_BUFFER_SIZE = 1000 }; +enum { WORK_BUFFER_SIZE = 1000 / sizeof (CHAR_T) }; /* This table maps a character into a number representing a class. In each step there is a destination label for each class. */ @@ -591,9 +591,8 @@ static const uint8_t jump_table[] = string = _itoa (number.longlong, workend, base, \ spec == L_('X')); \ if (group && grouping) \ - string = group_number (string, workend, grouping, \ - thousands_sep); \ - \ + string = group_number (work_buffer, string, workend, \ + grouping, thousands_sep); \ if (use_outdigits && base == 10) \ string = _i18n_number_rewrite (string, workend, workend); \ } \ @@ -649,9 +648,8 @@ static const uint8_t jump_table[] = string = _itoa_word (number.word, workend, base, \ spec == L_('X')); \ if (group && grouping) \ - string = group_number (string, workend, grouping, \ - thousands_sep); \ - \ + string = group_number (work_buffer, string, workend, \ + grouping, thousands_sep); \ if (use_outdigits && base == 10) \ string = _i18n_number_rewrite (string, workend, workend); \ } \ @@ -766,7 +764,8 @@ static const uint8_t jump_table[] = .pad = pad, \ .extra = 0, \ .i18n = use_outdigits, \ - .wide = sizeof (CHAR_T) != 1 }; \ + .wide = sizeof (CHAR_T) != 1, \ + .is_binary128 = 0}; \ \ if (is_long_double) \ the_arg.pa_long_double = va_arg (ap, long double); \ @@ -784,6 +783,8 @@ static const uint8_t jump_table[] = fspec->data_arg_type = PA_DOUBLE; \ fspec->info.is_long_double = 0; \ } \ + /* Not supported by *printf functions. */ \ + fspec->info.is_binary128 = 0; \ \ function_done = __printf_fp (s, &fspec->info, &ptr); \ } \ @@ -823,7 +824,8 @@ static const uint8_t jump_table[] = .group = group, \ .pad = pad, \ .extra = 0, \ - .wide = sizeof (CHAR_T) != 1 }; \ + .wide = sizeof (CHAR_T) != 1, \ + .is_binary128 = 0}; \ \ if (is_long_double) \ the_arg.pa_long_double = va_arg (ap, long double); \ @@ -838,6 +840,8 @@ static const uint8_t jump_table[] = ptr = (const void *) &args_value[fspec->data_arg]; \ if (__ldbl_is_dbl) \ fspec->info.is_long_double = 0; \ + /* Not supported by *printf functions. */ \ + fspec->info.is_binary128 = 0; \ \ function_done = __printf_fphex (s, &fspec->info, &ptr); \ } \ @@ -987,11 +991,10 @@ static const uint8_t jump_table[] = if (string == NULL) \ { \ /* Write "(null)" if there's space. */ \ - if (prec == -1 \ - || prec >= (int) (sizeof (null) / sizeof (null[0])) - 1) \ + if (prec == -1 || prec >= (int) array_length (null) - 1) \ { \ string = (CHAR_T *) null; \ - len = (sizeof (null) / sizeof (null[0])) - 1; \ + len = array_length (null) - 1; \ } \ else \ { \ @@ -1082,7 +1085,7 @@ static const uint8_t jump_table[] = LABEL (form_wcharacter): \ { \ /* Wide character. */ \ - char buf[MB_CUR_MAX]; \ + char buf[MB_LEN_MAX]; \ mbstate_t mbstate; \ size_t len; \ \ @@ -1212,10 +1215,10 @@ static const uint8_t jump_table[] = /* Helper function to provide temporary buffering for unbuffered streams. */ static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list) - __THROW __attribute__ ((noinline)) internal_function; + __THROW __attribute__ ((noinline)); /* Handle positional format specifiers. */ -static int printf_positional (_IO_FILE *s, +static int printf_positional (FILE *s, const CHAR_T *format, int readonly_format, va_list ap, va_list *ap_savep, int done, int nspecs_done, const UCHAR_T *lead_str_end, @@ -1227,8 +1230,8 @@ static int printf_unknown (FILE *, const struct printf_info *, const void *const *) __THROW; /* Group digits of number string. */ -static CHAR_T *group_number (CHAR_T *, CHAR_T *, const char *, THOUSANDS_SEP_T) - __THROW internal_function; +static CHAR_T *group_number (CHAR_T *, CHAR_T *, CHAR_T *, const char *, + THOUSANDS_SEP_T); /* The function itself. */ int @@ -1456,20 +1459,19 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) left = 1; } - if (__glibc_unlikely (width >= INT_MAX / sizeof (CHAR_T) - 32)) + if (__glibc_unlikely (width >= INT_MAX / sizeof (CHAR_T) - EXTSIZ)) { __set_errno (EOVERFLOW); done = -1; goto all_done; } - if (width >= WORK_BUFFER_SIZE - 32) + if (width >= WORK_BUFFER_SIZE - EXTSIZ) { - /* We have to use a special buffer. The "32" is just a safe - bet for all the output which is not counted in the width. */ - size_t needed = ((size_t) width + 32) * sizeof (CHAR_T); + /* We have to use a special buffer. */ + size_t needed = ((size_t) width + EXTSIZ) * sizeof (CHAR_T); if (__libc_use_alloca (needed)) - workend = (CHAR_T *) alloca (needed) + width + 32; + workend = (CHAR_T *) alloca (needed) + width + EXTSIZ; else { workstart = (CHAR_T *) malloc (needed); @@ -1478,7 +1480,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) done = -1; goto all_done; } - workend = workstart + width + 32; + workend = workstart + width + EXTSIZ; } } } @@ -1489,20 +1491,19 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) width = read_int (&f); if (__glibc_unlikely (width == -1 - || width >= INT_MAX / sizeof (CHAR_T) - 32)) + || width >= INT_MAX / sizeof (CHAR_T) - EXTSIZ)) { __set_errno (EOVERFLOW); done = -1; goto all_done; } - if (width >= WORK_BUFFER_SIZE - 32) + if (width >= WORK_BUFFER_SIZE - EXTSIZ) { - /* We have to use a special buffer. The "32" is just a safe - bet for all the output which is not counted in the width. */ - size_t needed = ((size_t) width + 32) * sizeof (CHAR_T); + /* We have to use a special buffer. */ + size_t needed = ((size_t) width + EXTSIZ) * sizeof (CHAR_T); if (__libc_use_alloca (needed)) - workend = (CHAR_T *) alloca (needed) + width + 32; + workend = (CHAR_T *) alloca (needed) + width + EXTSIZ; else { workstart = (CHAR_T *) malloc (needed); @@ -1511,7 +1512,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) done = -1; goto all_done; } - workend = workstart + width + 32; + workend = workstart + width + EXTSIZ; } } if (*f == L_('$')) @@ -1562,18 +1563,23 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) } else prec = 0; - if (prec > width && prec > WORK_BUFFER_SIZE - 32) + if (prec > width && prec > WORK_BUFFER_SIZE - EXTSIZ) { - if (__glibc_unlikely (prec >= INT_MAX / sizeof (CHAR_T) - 32)) + /* Deallocate any previously allocated buffer because it is + too small. */ + if (__glibc_unlikely (workstart != NULL)) + free (workstart); + workstart = NULL; + if (__glibc_unlikely (prec >= INT_MAX / sizeof (CHAR_T) - EXTSIZ)) { __set_errno (EOVERFLOW); done = -1; goto all_done; } - size_t needed = ((size_t) prec + 32) * sizeof (CHAR_T); + size_t needed = ((size_t) prec + EXTSIZ) * sizeof (CHAR_T); if (__libc_use_alloca (needed)) - workend = (CHAR_T *) alloca (needed) + prec + 32; + workend = (CHAR_T *) alloca (needed) + prec + EXTSIZ; else { workstart = (CHAR_T *) malloc (needed); @@ -1582,7 +1588,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) done = -1; goto all_done; } - workend = workstart + prec + 32; + workend = workstart + prec + EXTSIZ; } } JUMP (*f, step2_jumps); @@ -1689,21 +1695,23 @@ do_positional: } static int -printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, +printf_positional (FILE *s, const CHAR_T *format, int readonly_format, va_list ap, va_list *ap_savep, int done, int nspecs_done, const UCHAR_T *lead_str_end, CHAR_T *work_buffer, int save_errno, const char *grouping, THOUSANDS_SEP_T thousands_sep) { - /* For the argument descriptions, which may be allocated on the heap. */ - void *args_malloced = NULL; - /* For positional argument handling. */ struct scratch_buffer specsbuf; scratch_buffer_init (&specsbuf); struct printf_spec *specs = specsbuf.data; size_t specs_limit = specsbuf.length / sizeof (specs[0]); + /* Used as a backing store for args_value, args_size, args_type + below. */ + struct scratch_buffer argsbuf; + scratch_buffer_init (&argsbuf); + /* Array with information about the needed arguments. This has to be dynamically extensible. */ size_t nspecs = 0; @@ -1712,10 +1720,6 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, determine the size of the array needed to store the argument attributes. */ size_t nargs = 0; - size_t bytes_per_arg; - union printf_arg *args_value; - int *args_size; - int *args_type; /* Positional parameters refer to arguments directly. This could also determine the maximum number of arguments. Track the @@ -1765,38 +1769,29 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, /* Determine the number of arguments the format string consumes. */ nargs = MAX (nargs, max_ref_arg); - /* Calculate total size needed to represent a single argument across - all three argument-related arrays. */ - bytes_per_arg = (sizeof (*args_value) + sizeof (*args_size) - + sizeof (*args_type)); - - /* Check for potential integer overflow. */ - if (__glibc_unlikely (nargs > INT_MAX / bytes_per_arg)) - { - __set_errno (EOVERFLOW); - done = -1; - goto all_done; - } - - /* Allocate memory for all three argument arrays. */ - if (__libc_use_alloca (nargs * bytes_per_arg)) - args_value = alloca (nargs * bytes_per_arg); - else - { - args_value = args_malloced = malloc (nargs * bytes_per_arg); - if (args_value == NULL) - { - done = -1; - goto all_done; - } - } - /* Set up the remaining two arrays to each point past the end of the - prior array, since space for all three has been allocated now. */ - args_size = &args_value[nargs].pa_int; - args_type = &args_size[nargs]; - memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0', - nargs * sizeof (*args_type)); + union printf_arg *args_value; + int *args_size; + int *args_type; + { + /* Calculate total size needed to represent a single argument + across all three argument-related arrays. */ + size_t bytes_per_arg + = sizeof (*args_value) + sizeof (*args_size) + sizeof (*args_type); + if (!scratch_buffer_set_array_size (&argsbuf, nargs, bytes_per_arg)) + { + done = -1; + goto all_done; + } + args_value = argsbuf.data; + /* Set up the remaining two arrays to each point past the end of + the prior array, since space for all three has been allocated + now. */ + args_size = &args_value[nargs].pa_int; + args_type = &args_size[nargs]; + memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0', + nargs * sizeof (*args_type)); + } /* XXX Could do sanity check here: If any element in ARGS_TYPE is still zero after this loop, format is invalid. For now we @@ -1959,23 +1954,23 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, } /* Maybe the buffer is too small. */ - if (MAX (prec, width) + 32 > WORK_BUFFER_SIZE) + if (MAX (prec, width) + EXTSIZ > WORK_BUFFER_SIZE) { - if (__libc_use_alloca ((MAX (prec, width) + 32) + if (__libc_use_alloca ((MAX (prec, width) + EXTSIZ) * sizeof (CHAR_T))) - workend = ((CHAR_T *) alloca ((MAX (prec, width) + 32) + workend = ((CHAR_T *) alloca ((MAX (prec, width) + EXTSIZ) * sizeof (CHAR_T)) - + (MAX (prec, width) + 32)); + + (MAX (prec, width) + EXTSIZ)); else { - workstart = (CHAR_T *) malloc ((MAX (prec, width) + 32) + workstart = (CHAR_T *) malloc ((MAX (prec, width) + EXTSIZ) * sizeof (CHAR_T)); if (workstart == NULL) { done = -1; goto all_done; } - workend = workstart + (MAX (prec, width) + 32); + workend = workstart + (MAX (prec, width) + EXTSIZ); } } @@ -2062,10 +2057,9 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, - specs[nspecs_done].end_of_fmt); } all_done: - if (__glibc_unlikely (args_malloced != NULL)) - free (args_malloced); if (__glibc_unlikely (workstart != NULL)) free (workstart); + scratch_buffer_free (&argsbuf); scratch_buffer_free (&specsbuf); return done; } @@ -2122,16 +2116,20 @@ printf_unknown (FILE *s, const struct printf_info *info, return done; } -/* Group the digits according to the grouping rules of the current locale. - The interpretation of GROUPING is as in `struct lconv' from <locale.h>. */ +/* Group the digits from W to REAR_PTR according to the grouping rules + of the current locale. The interpretation of GROUPING is as in + `struct lconv' from <locale.h>. The grouped number extends from + the returned pointer until REAR_PTR. FRONT_PTR to W is used as a + scratch area. */ static CHAR_T * -internal_function -group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping, - THOUSANDS_SEP_T thousands_sep) +group_number (CHAR_T *front_ptr, CHAR_T *w, CHAR_T *rear_ptr, + const char *grouping, THOUSANDS_SEP_T thousands_sep) { + /* Length of the current group. */ int len; - CHAR_T *src, *s; #ifndef COMPILE_WPRINTF + /* Length of the separator (in wide mode, the separator is always a + single wide character). */ int tlen = strlen (thousands_sep); #endif @@ -2144,26 +2142,34 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping, len = *grouping++; /* Copy existing string so that nothing gets overwritten. */ - src = (CHAR_T *) alloca ((rear_ptr - w) * sizeof (CHAR_T)); - s = (CHAR_T *) __mempcpy (src, w, - (rear_ptr - w) * sizeof (CHAR_T)); + memmove (front_ptr, w, (rear_ptr - w) * sizeof (CHAR_T)); + CHAR_T *s = front_ptr + (rear_ptr - w); + w = rear_ptr; /* Process all characters in the string. */ - while (s > src) + while (s > front_ptr) { *--w = *--s; - if (--len == 0 && s > src) + if (--len == 0 && s > front_ptr) { /* A new group begins. */ #ifdef COMPILE_WPRINTF - *--w = thousands_sep; + if (w != s) + *--w = thousands_sep; + else + /* Not enough room for the separator. */ + goto copy_rest; #else int cnt = tlen; - do - *--w = thousands_sep[--cnt]; - while (cnt > 0); + if (tlen < w - s) + do + *--w = thousands_sep[--cnt]; + while (cnt > 0); + else + /* Not enough room for the separator. */ + goto copy_rest; #endif if (*grouping == CHAR_MAX @@ -2172,17 +2178,16 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping, #endif ) { - /* No further grouping to be done. - Copy the rest of the number. */ - do - *--w = *--s; - while (s > src); + copy_rest: + /* No further grouping to be done. Copy the rest of the + number. */ + memmove (w, s, (front_ptr -s) * sizeof (CHAR_T)); break; } else if (*grouping != '\0') - /* The previous grouping repeats ad infinitum. */ len = *grouping++; else + /* The previous grouping repeats ad infinitum. */ len = grouping[-1]; } } @@ -2196,22 +2201,21 @@ struct helper_file #ifdef COMPILE_WPRINTF struct _IO_wide_data _wide_data; #endif - _IO_FILE *_put_stream; + FILE *_put_stream; #ifdef _IO_MTSAFE_IO _IO_lock_t lock; #endif }; static int -_IO_helper_overflow (_IO_FILE *s, int c) +_IO_helper_overflow (FILE *s, int c) { - _IO_FILE *target = ((struct helper_file*) s)->_put_stream; + FILE *target = ((struct helper_file*) s)->_put_stream; #ifdef COMPILE_WPRINTF int used = s->_wide_data->_IO_write_ptr - s->_wide_data->_IO_write_base; if (used) { - _IO_size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base, - used); + size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base, used); if (written == 0 || written == WEOF) return WEOF; __wmemmove (s->_wide_data->_IO_write_base, @@ -2223,7 +2227,7 @@ _IO_helper_overflow (_IO_FILE *s, int c) int used = s->_IO_write_ptr - s->_IO_write_base; if (used) { - _IO_size_t written = _IO_sputn (target, s->_IO_write_base, used); + size_t written = _IO_sputn (target, s->_IO_write_base, used); if (written == 0 || written == EOF) return EOF; memmove (s->_IO_write_base, s->_IO_write_base + written, @@ -2235,7 +2239,7 @@ _IO_helper_overflow (_IO_FILE *s, int c) } #ifdef COMPILE_WPRINTF -static const struct _IO_jump_t _IO_helper_jumps = +static const struct _IO_jump_t _IO_helper_jumps libio_vtable = { JUMP_INIT_DUMMY, JUMP_INIT (finish, _IO_wdefault_finish), @@ -2257,7 +2261,7 @@ static const struct _IO_jump_t _IO_helper_jumps = JUMP_INIT (stat, _IO_default_stat) }; #else -static const struct _IO_jump_t _IO_helper_jumps = +static const struct _IO_jump_t _IO_helper_jumps libio_vtable = { JUMP_INIT_DUMMY, JUMP_INIT (finish, _IO_default_finish), @@ -2281,13 +2285,11 @@ static const struct _IO_jump_t _IO_helper_jumps = #endif static int -internal_function -buffered_vfprintf (_IO_FILE *s, const CHAR_T *format, - _IO_va_list args) +buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args) { - CHAR_T buf[_IO_BUFSIZ]; + CHAR_T buf[BUFSIZ]; struct helper_file helper; - _IO_FILE *hp = (_IO_FILE *) &helper._f; + FILE *hp = (FILE *) &helper._f; int result, to_flush; /* Orient the stream. */ @@ -2305,7 +2307,7 @@ buffered_vfprintf (_IO_FILE *s, const CHAR_T *format, _IO_setp (hp, buf, buf + sizeof buf); hp->_mode = -1; #endif - hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS|_IO_USER_LOCK; + hp->_flags = _IO_MAGIC|_IO_NO_READS|_IO_USER_LOCK; #if _IO_JUMPS_OFFSET hp->_vtable_offset = 0; #endif diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index 8cd59557a6..1ce836a324 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 @@ -27,7 +27,7 @@ #include <string.h> #include <wchar.h> #include <wctype.h> -#include <libc-internal.h> +#include <libc-diag.h> #include <libc-lock.h> #include <locale/localeinfo.h> #include <scratch_buffer.h> @@ -72,10 +72,6 @@ #include <locale/localeinfo.h> #include <libioP.h> -#include <libio.h> - -#undef va_list -#define va_list _IO_va_list #ifdef COMPILE_WSCANF # define ungetc(c, s) ((void) (c == WEOF \ @@ -133,6 +129,8 @@ # define WINT_T int #endif +#include "printf-parse.h" /* Use read_int. */ + #define encode_error() do { \ errval = 4; \ __set_errno (EILSEQ); \ @@ -174,7 +172,7 @@ } \ else if (format == NULL) \ { \ - MAYBE_SET_EINVAL; \ + __set_errno (EINVAL); \ return EOF; \ } \ } while (0) @@ -269,11 +267,11 @@ char_buffer_add (struct char_buffer *buffer, CHAR_T ch) Return the number of assignments made, or -1 for an input error. */ #ifdef COMPILE_WSCANF int -_IO_vfwscanf (_IO_FILE *s, const wchar_t *format, _IO_va_list argptr, +_IO_vfwscanf (FILE *s, const wchar_t *format, va_list argptr, int *errp) #else int -_IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, +_IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, int *errp) #endif { @@ -287,14 +285,14 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, int flags; /* Modifiers for current format element. */ int errval = 0; #ifndef COMPILE_WSCANF - __locale_t loc = _NL_CURRENT_LOCALE; + locale_t loc = _NL_CURRENT_LOCALE; struct __locale_data *const curctype = loc->__locales[LC_CTYPE]; #endif /* Errno of last failed inchar call. */ int inchar_errno = 0; /* Status for reading F-P nums. */ - char got_digit, got_dot, got_e, negative; + char got_digit, got_dot, got_e, got_sign; /* If a [...] is a [^...]. */ CHAR_T not_in; #define exp_char not_in @@ -488,9 +486,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* Check for a positional parameter specification. */ if (ISDIGIT ((UCHAR_T) *f)) { - argpos = (UCHAR_T) *f++ - L_('0'); - while (ISDIGIT ((UCHAR_T) *f)) - argpos = argpos * 10 + ((UCHAR_T) *f++ - L_('0')); + argpos = read_int ((const UCHAR_T **) &f); if (*f == L_('$')) ++f; else @@ -525,11 +521,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* Find the maximum field width. */ width = 0; - while (ISDIGIT ((UCHAR_T) *f)) - { - width *= 10; - width += (UCHAR_T) *f++ - L_('0'); - } + if (ISDIGIT ((UCHAR_T) *f)) + width = read_int ((const UCHAR_T **) &f); got_width: if (width == 0) width = -1; @@ -757,7 +750,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, size_t n; if (!(flags & SUPPRESS) && (flags & POSIX_MALLOC) - && str + MB_CUR_MAX >= *strptr + strsize) + && *strptr + strsize - str <= MB_LEN_MAX) { /* We have to enlarge the buffer if the `m' flag was given. */ @@ -769,7 +762,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, { /* Can't allocate that much. Last-ditch effort. */ newstr = (char *) realloc (*strptr, - strleng + MB_CUR_MAX); + strleng + MB_LEN_MAX); if (newstr == NULL) { /* c can't have `a' flag, only `m'. */ @@ -780,7 +773,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, { *strptr = newstr; str = newstr + strleng; - strsize = strleng + MB_CUR_MAX; + strsize = strleng + MB_LEN_MAX; } } else @@ -1048,7 +1041,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, size_t n; if (!(flags & SUPPRESS) && (flags & MALLOC) - && str + MB_CUR_MAX >= *strptr + strsize) + && *strptr + strsize - str <= MB_LEN_MAX) { /* We have to enlarge the buffer if the `a' or `m' flag was given. */ @@ -1061,7 +1054,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* Can't allocate that much. Last-ditch effort. */ newstr = (char *) realloc (*strptr, - strleng + MB_CUR_MAX); + strleng + MB_LEN_MAX); if (newstr == NULL) { if (flags & POSIX_MALLOC) @@ -1081,7 +1074,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, { *strptr = newstr; str = newstr + strleng; - strsize = strleng + MB_CUR_MAX; + strsize = strleng + MB_LEN_MAX; } } else @@ -1097,7 +1090,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, if (__glibc_unlikely (n == (size_t) -1)) encode_error (); - assert (n <= MB_CUR_MAX); + assert (n <= MB_LEN_MAX); str += n; } #else @@ -1921,20 +1914,19 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, if (__glibc_unlikely (c == EOF)) input_error (); - got_digit = got_dot = got_e = 0; + got_digit = got_dot = got_e = got_sign = 0; /* Check for a sign. */ if (c == L_('-') || c == L_('+')) { - negative = c == L_('-'); + got_sign = 1; + char_buffer_add (&charbuf, c); if (__glibc_unlikely (width == 0 || inchar () == EOF)) /* EOF is only an input error before we read any chars. */ conv_error (); if (width > 0) --width; } - else - negative = 0; /* Take care for the special arguments "nan" and "inf". */ if (TOLOWER (c) == L_('n')) @@ -2183,7 +2175,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, digits with ASCII letters. */ && !(flags & HEXA_FLOAT) /* Minimum requirement. */ - && (char_buffer_size (&charbuf) == 0 || got_dot) + && (char_buffer_size (&charbuf) == got_sign || got_dot) && (map = __wctrans ("to_inpunct")) != NULL) { /* Reget the first character. */ @@ -2202,8 +2194,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, for localized FP numbers, then we may have localized digits. Note, we test GOT_DOT above. */ #ifdef COMPILE_WSCANF - if (char_buffer_size (&charbuf) == 0 - || (char_buffer_size (&charbuf) == 1 + if (char_buffer_size (&charbuf) == got_sign + || (char_buffer_size (&charbuf) == got_sign + 1 && wcdigits[11] == decimal)) #else char mbdigits[12][MB_LEN_MAX + 1]; @@ -2211,13 +2203,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, mbstate_t state; memset (&state, '\0', sizeof (state)); - bool match_so_far = char_buffer_size (&charbuf) == 0; + bool match_so_far = char_buffer_size (&charbuf) == got_sign; size_t mblen = __wcrtomb (mbdigits[11], wcdigits[11], &state); if (mblen != (size_t) -1) { mbdigits[11][mblen] = '\0'; match_so_far |= - (char_buffer_size (&charbuf) == strlen (decimal) + (char_buffer_size (&charbuf) == strlen (decimal) + got_sign && strcmp (decimal, mbdigits[11]) == 0); } else @@ -2227,7 +2219,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, from a file. */ if (decimal_len <= MB_LEN_MAX) { - match_so_far |= char_buffer_size (&charbuf) == decimal_len; + match_so_far |= (char_buffer_size (&charbuf) + == decimal_len + got_sign); memcpy (mbdigits[11], decimal, decimal_len + 1); } else @@ -2291,7 +2284,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, if (got_e && charbuf.current[-1] == exp_char && (c == L_('-') || c == L_('+'))) char_buffer_add (&charbuf, c); - else if (char_buffer_size (&charbuf) > 0 && !got_e + else if (char_buffer_size (&charbuf) > got_sign && !got_e && (CHAR_T) TOLOWER (c) == exp_char) { char_buffer_add (&charbuf, exp_char); @@ -2415,9 +2408,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* 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. */ - if (__glibc_unlikely (char_buffer_size (&charbuf) == 0 + if (__glibc_unlikely (char_buffer_size (&charbuf) == got_sign || ((flags & HEXA_FLOAT) - && char_buffer_size (&charbuf) == 2))) + && (char_buffer_size (&charbuf) + == 2 + got_sign)))) conv_error (); scan_float: @@ -2434,21 +2428,21 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, long double d = __strtold_internal (char_buffer_start (&charbuf), &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf)) - *ARG (long double *) = negative ? -d : d; + *ARG (long double *) = d; } else if (flags & (LONG | LONGDBL)) { double d = __strtod_internal (char_buffer_start (&charbuf), &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf)) - *ARG (double *) = negative ? -d : d; + *ARG (double *) = d; } else { float d = __strtof_internal (char_buffer_start (&charbuf), &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf)) - *ARG (float *) = negative ? -d : d; + *ARG (float *) = d; } if (__glibc_unlikely (tw == char_buffer_start (&charbuf))) @@ -2675,7 +2669,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* Possibly correct character, just not enough input. */ ++cnt; - assert (cnt < MB_CUR_MAX); + assert (cnt < MB_LEN_MAX); continue; } cnt = 0; @@ -2827,7 +2821,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, if (!(flags & SUPPRESS)) { if ((flags & MALLOC) - && str + MB_CUR_MAX >= *strptr + strsize) + && *strptr + strsize - str <= MB_LEN_MAX) { /* Enlarge the buffer. */ size_t strleng = str - *strptr; @@ -2839,7 +2833,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* Can't allocate that much. Last-ditch effort. */ newstr = (char *) realloc (*strptr, - strleng + MB_CUR_MAX); + strleng + MB_LEN_MAX); if (newstr == NULL) { if (flags & POSIX_MALLOC) @@ -2859,7 +2853,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, { *strptr = newstr; str = newstr + strleng; - strsize = strleng + MB_CUR_MAX; + strsize = strleng + MB_LEN_MAX; } } else @@ -2875,7 +2869,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, if (__glibc_unlikely (n == (size_t) -1)) encode_error (); - assert (n <= MB_CUR_MAX); + assert (n <= MB_LEN_MAX); str += n; } while (--width > 0 && inchar () != WEOF); diff --git a/stdio-common/vprintf.c b/stdio-common/vprintf.c index df66e18045..d459642dc8 100644 --- a/stdio-common/vprintf.c +++ b/stdio-common/vprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 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 |