diff --git a/ChangeLog b/ChangeLog index f343428..e416cd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,109 @@ +2014-12-16 Florian Weimer + + [BZ #17630] + * resolv/nss_dns/dns-network.c (getanswer_r): Iterate over alias + names. + +2014-12-15 Jeff Law + + [BZ #16617] + * stdio-common/vfprintf.c (vfprintf): Allocate large specs array + on the heap. (CVE-2012-3406) + * stdio-common/bug23-2.c, stdio-common/bug23-3.c: New file. + * stdio-common/bug23-4.c: New file. Test case by Joseph Myers. + * stdio-common/Makefile (tests): Add bug23-2, bug23-3, bug23-4. + +2014-11-24 Siddhesh Poyarekar + + [BZ #17266] + * misc/sys/cdefs.h: Define __extern_always_inline for clang + 4.2 and newer. + +2014-11-19 Carlos O'Donell + Florian Weimer + Joseph Myers + Adam Conrad + Andreas Schwab + Brooks + + [BZ #17625] + * wordexp-test.c (__dso_handle): Add prototype. + (__register_atfork): Likewise. + (__app_register_atfork): New function. + (registered_forks): New global. + (register_fork): New function. + (test_case): Add 3 new tests for WRDE_CMDSUB. + (main): Call __app_register_atfork. + (testit): If WRDE_NOCMD set registered_forks to zero, run test, and if + fork count is non-zero fail the test. + * posix/wordexp.c (exec_comm): Return WRDE_CMDSUB if WRDE_NOCMD flag + is set. + (parse_dollars): Remove check for WRDE_NOCMD. + (parse_dquote): Likewise. + +2014-11-10 Renlin Li + + [BZ #17555] + * sysdeps/aarch64/start.S (_start): Delete x29 overwritten assignment. + +2014-10-22 Maciej W. Rozycki + + [BZ #17485] + * sysdeps/unix/sysv/linux/mips/vfork.S (__libc_vfork): Define. + +2014-10-08 Roland McGrath + + [BZ #17460] + * nscd/nscd.c (more_help): Rewrite list of tables collection + using xstrdup and asprintf. + + * nscd/nscd_conf.c: Remove local xstrdup declaration. + +2014-10-09 Allan McRae + + * po/fr.po: Update French translation from translation project. + +2014-09-16 Siddhesh Poyarekar + + [BZ #17370] + * libio/wfileops.c (do_ftell_wide): Free OUT on error path. + +2014-09-11 Tim Lammens + + [BZ #17370] + * libio/wfileops (do_ftell_wide): Free OUT. + +2014-09-16 Siddhesh Poyarekar + Jakub Jelinek + + [BZ #17266] + * libio/stdio.h: Check definition of __fortify_function + instead of __extern_always_inline to include bits/stdio2.h. + * math/bits/math-finite.h [__USE_XOPEN || __USE_ISOC99]: Also + check if __extern_always_inline is defined. + [__USE_MISC || __USE_XOPEN]: Likewise. + [__USE_ISOC99] Likewise. + * misc/sys/cdefs.h (__fortify_function): Define only if + __extern_always_inline is defined. + [!__cplusplus || __GNUC_PREREQ (4,3)]: Revert to defining + __extern_always_inline and __extern_inline only for g++-4.3 + and newer or a compatible gcc. + +2014-09-15 Andreas Schwab + + [BZ #17371] + * sysdeps/unix/sysv/linux/ifaddrs.c (getifaddrs_internal): Fix + last change to handle zero prefix length. + +2014-09-12 Joseph Myers + + * sysdeps/gnu/netinet/udp.h (UDP_NO_CHECK6_TX): New macro. + (UDP_NO_CHECK6_RX): Likewise. + +2014-09-13 Allan McRae + + * po/ru.po: Update Russian translation from translation project. + 2014-09-07 Allan McRae using `glibc' in the "product" field. +Version 2.20.1 + +* The following bugs are resolved with this release: + + 16617, 17266, 17370, 17371, 17460, 17485, 17555, 17625, 17630. + +* CVE-2104-7817 The wordexp function could ignore the WRDE_NOCMD flag + under certain input conditions resulting in the execution of a shell for + command substitution when the applicaiton did not request it. The + implementation now checks WRDE_NOCMD immediately before executing the + shell and returns the error WRDE_CMDSUB as expected. + +* CVE-2012-3406 printf-style functions could run into a stack overflow when + processing format strings with a large number of format specifiers. + +* CVE-2014-9402 The nss_dns implementation of getnetbyname could run into an + infinite loopif the DNS response contained a PTR record of an unexpected + format. + Version 2.20 * The following bugs are resolved with this release: diff --git a/libio/stdio.h b/libio/stdio.h index d8c0bdb..1f4f837 100644 --- a/libio/stdio.h +++ b/libio/stdio.h @@ -932,7 +932,7 @@ extern void funlockfile (FILE *__stream) __THROW; #ifdef __USE_EXTERN_INLINES # include #endif -#if __USE_FORTIFY_LEVEL > 0 && defined __extern_always_inline +#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function # include #endif #ifdef __LDBL_COMPAT diff --git a/libio/wfileops.c b/libio/wfileops.c index f123add..c5ec5f7 100644 --- a/libio/wfileops.c +++ b/libio/wfileops.c @@ -708,9 +708,13 @@ do_ftell_wide (_IO_FILE *fp) sequences must be complete since they are accepted as wchar_t; if not, then that is an error. */ if (__glibc_unlikely (status != __codecvt_ok)) - return WEOF; + { + free (out); + return WEOF; + } offset += outstop - out; + free (out); } /* We don't trust _IO_read_end to represent the current file offset diff --git a/math/bits/math-finite.h b/math/bits/math-finite.h index aa755de..0656645 100644 --- a/math/bits/math-finite.h +++ b/math/bits/math-finite.h @@ -251,7 +251,8 @@ extern long double __REDIRECT_NTH (lgammal_r, (long double, int *), # endif #endif -#if defined __USE_XOPEN || defined __USE_ISOC99 +#if ((defined __USE_XOPEN || defined __USE_ISOC99) \ + && defined __extern_always_inline) /* lgamma. */ __extern_always_inline double __NTH (lgamma (double __d)) { @@ -284,7 +285,8 @@ __extern_always_inline long double __NTH (lgammal (long double __d)) # endif #endif -#if defined __USE_MISC || defined __USE_XOPEN +#if ((defined __USE_MISC || defined __USE_XOPEN) \ + && defined __extern_always_inline) /* gamma. */ __extern_always_inline double __NTH (gamma (double __d)) { @@ -422,7 +424,7 @@ extern long double __REDIRECT_NTH (sqrtl, (long double), __sqrtl_finite); # endif #endif -#ifdef __USE_ISOC99 +#if defined __USE_ISOC99 && defined __extern_always_inline /* tgamma. */ extern double __gamma_r_finite (double, int *); __extern_always_inline double __NTH (tgamma (double __d)) diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h index 04db956..711ac1d 100644 --- a/misc/sys/cdefs.h +++ b/misc/sys/cdefs.h @@ -131,7 +131,6 @@ /* Fortify support. */ #define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) #define __bos0(ptr) __builtin_object_size (ptr, 0) -#define __fortify_function __extern_always_inline __attribute_artificial__ #if __GNUC_PREREQ (4,3) # define __warndecl(name, msg) \ @@ -318,12 +317,19 @@ # define __attribute_artificial__ /* Ignore */ #endif -#ifdef __GNUC__ -/* One of these will be defined if the __gnu_inline__ attribute is - available. In C++, __GNUC_GNU_INLINE__ will be defined even though - __inline does not use the GNU inlining rules. If neither macro is - defined, this version of GCC only supports GNU inline semantics. */ -# if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. Using __GNUC_STDC_INLINE__ + or __GNUC_GNU_INLINE is not a good enough check for gcc because gcc versions + older than 4.3 may define these macros and still not guarantee GNU inlining + semantics. + + clang++ identifies itself as gcc-4.2, but has support for GNU inlining + semantics, that can be checked fot by using the __GNUC_STDC_INLINE_ and + __GNUC_GNU_INLINE__ macro definitions. */ +#if (!defined __cplusplus || __GNUC_PREREQ (4,3) \ + || (defined __clang__ && (defined __GNUC_STDC_INLINE__ \ + || defined __GNUC_GNU_INLINE__))) +# if defined __GNUC_STDC_INLINE__ || defined __cplusplus # define __extern_inline extern __inline __attribute__ ((__gnu_inline__)) # define __extern_always_inline \ extern __always_inline __attribute__ ((__gnu_inline__)) @@ -331,9 +337,10 @@ # define __extern_inline extern __inline # define __extern_always_inline extern __always_inline # endif -#else /* Not GCC. */ -# define __extern_inline /* Ignore */ -# define __extern_always_inline /* Ignore */ +#endif + +#ifdef __extern_always_inline +# define __fortify_function __extern_always_inline __attribute_artificial__ #endif /* GCC 4.3 and above allow passing all anonymous arguments of an diff --git a/nscd/nscd.c b/nscd/nscd.c index 7131ead..b7704b3 100644 --- a/nscd/nscd.c +++ b/nscd/nscd.c @@ -451,33 +451,36 @@ parse_opt (int key, char *arg, struct argp_state *state) static char * more_help (int key, const char *text, void *input) { - char *tables, *tp = NULL; - switch (key) { case ARGP_KEY_HELP_EXTRA: { - dbtype cnt; + /* We print some extra information. */ - tables = xmalloc (sizeof (dbnames) + 1); - for (cnt = 0; cnt < lastdb; cnt++) + char *tables = xstrdup (dbnames[0]); + for (dbtype i = 1; i < lastdb; ++i) { - strcat (tables, dbnames[cnt]); - strcat (tables, " "); + char *more_tables; + if (asprintf (&more_tables, "%s %s", tables, dbnames[i]) < 0) + more_tables = NULL; + free (tables); + if (more_tables == NULL) + return NULL; + tables = more_tables; } - } - /* We print some extra information. */ - if (asprintf (&tp, gettext ("\ + char *tp; + if (asprintf (&tp, gettext ("\ Supported tables:\n\ %s\n\ \n\ For bug reporting instructions, please see:\n\ %s.\n\ "), tables, REPORT_BUGS_TO) < 0) - tp = NULL; - free (tables); - return tp; + tp = NULL; + free (tables); + return tp; + } default: break; @@ -622,15 +625,15 @@ monitor_child (int fd) } if (WIFEXITED (status)) - { - child_ret = WEXITSTATUS (status); - fprintf (stderr, _("child exited with status %d\n"), child_ret); - } + { + child_ret = WEXITSTATUS (status); + fprintf (stderr, _("child exited with status %d\n"), child_ret); + } if (WIFSIGNALED (status)) - { - child_ret = WTERMSIG (status); - fprintf (stderr, _("child terminated by signal %d\n"), child_ret); - } + { + child_ret = WTERMSIG (status); + fprintf (stderr, _("child terminated by signal %d\n"), child_ret); + } } /* We have the child status, so exit with that code. */ diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c index 7856ed9..c8e194d 100644 --- a/nscd/nscd_conf.c +++ b/nscd/nscd_conf.c @@ -32,9 +32,6 @@ #include "dbg_log.h" #include "nscd.h" -/* Wrapper functions with error checking for standard functions. */ -extern char *xstrdup (const char *s); - /* Names of the databases. */ const char *const dbnames[lastdb] = diff --git a/po/fr.po b/po/fr.po index fbf564a..bb7a924 100644 --- a/po/fr.po +++ b/po/fr.po @@ -6673,11 +6673,11 @@ msgstr "Erreur d'entrée/sortie sur l'hôte cible" #: sysdeps/gnu/errlist.c:1399 msgid "No medium found" -msgstr "Aucun medium trouvé" +msgstr "Aucun médium trouvé" #: sysdeps/gnu/errlist.c:1407 msgid "Wrong medium type" -msgstr "Mauvais type de medium" +msgstr "Mauvais type de médium" #: sysdeps/gnu/errlist.c:1415 msgid "Required key not available" diff --git a/po/ru.po b/po/ru.po index 8596b47..d3d0973 100644 --- a/po/ru.po +++ b/po/ru.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: libc 2.19.90\n" "POT-Creation-Date: 2014-08-09 17:06+1000\n" -"PO-Revision-Date: 2014-08-21 14:55+0400\n" +"PO-Revision-Date: 2014-09-10 16:38+0400\n" "Last-Translator: Yuri Kozlov \n" "Language-Team: Russian \n" "Language: ru\n" @@ -76,7 +76,7 @@ msgstr "Выдает краткую информацию об использов #: iconv/iconv_prog.c:60 iconv/iconv_prog.c:61 nscd/nscd.c:105 #: nss/makedb.c:120 msgid "NAME" -msgstr "ФАЙЛ" +msgstr "ИМЯ" #: argp/argp-parse.c:104 msgid "Set the program name" @@ -123,7 +123,7 @@ msgstr "" #: catgets/gencat.c:110 msgid "Create C header file NAME containing symbol definitions" -msgstr "Создает заголовочный ФАЙЛ на Си, содержащий определения символов." +msgstr "Создает заголовочный файл с ИМЕНЕМ на Си, содержащий определения символов." #: catgets/gencat.c:112 msgid "Do not use existing catalog, force new output file" @@ -131,7 +131,7 @@ msgstr "Не использовать существующий каталог, #: catgets/gencat.c:113 nss/makedb.c:120 msgid "Write output to file NAME" -msgstr "Записать вывод в ФАЙЛ" +msgstr "Записать вывод в файл с ИМЕНЕМ" #: catgets/gencat.c:118 msgid "" @@ -4098,7 +4098,7 @@ msgstr "Перезагрузка «%s (%s,%s,%s)» в кэше netgroup!" #: nscd/nscd.c:106 msgid "Read configuration data from NAME" -msgstr "Читать конфигурационные данные из ФАЙЛА" +msgstr "Читать конфигурационные данные из файла с ИМЕНЕМ" #: nscd/nscd.c:108 msgid "Do not fork and display messages on the current tty" diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c index 4957006..bdd65e4 100644 --- a/posix/wordexp-test.c +++ b/posix/wordexp-test.c @@ -27,6 +27,25 @@ #define IFS " \n\t" +extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden"))); +extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *); + +static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void)) +{ + return __register_atfork (prepare, parent, child, + &__dso_handle == NULL ? NULL : __dso_handle); +} + +/* Number of forks seen. */ +static int registered_forks; + +/* For each fork increment the fork count. */ +static void +register_fork (void) +{ + registered_forks++; +} + struct test_case_struct { int retval; @@ -206,6 +225,12 @@ struct test_case_struct { WRDE_SYNTAX, NULL, "$((2+))", 0, 0, { NULL, }, IFS }, { WRDE_SYNTAX, NULL, "`", 0, 0, { NULL, }, IFS }, { WRDE_SYNTAX, NULL, "$((010+4+))", 0, 0, { NULL }, IFS }, + /* Test for CVE-2014-7817. We test 3 combinations of command + substitution inside an arithmetic expression to make sure that + no commands are executed and error is returned. */ + { WRDE_CMDSUB, NULL, "$((`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS }, + { WRDE_CMDSUB, NULL, "$((1+`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS }, + { WRDE_CMDSUB, NULL, "$((1+$((`echo 1`))))", WRDE_NOCMD, 0, { NULL, }, IFS }, { -1, NULL, NULL, 0, 0, { NULL, }, IFS }, }; @@ -258,6 +283,15 @@ main (int argc, char *argv[]) return -1; } + /* If we are not allowed to do command substitution, we install + fork handlers to verify that no forks happened. No forks should + happen at all if command substitution is disabled. */ + if (__app_register_atfork (register_fork, NULL, NULL) != 0) + { + printf ("Failed to register fork handler.\n"); + return -1; + } + for (test = 0; test_case[test].retval != -1; test++) if (testit (&test_case[test])) ++fail; @@ -367,6 +401,9 @@ testit (struct test_case_struct *tc) printf ("Test %d (%s): ", ++tests, tc->words); + if (tc->flags & WRDE_NOCMD) + registered_forks = 0; + if (tc->flags & WRDE_APPEND) { /* initial wordexp() call, to be appended to */ @@ -378,6 +415,13 @@ testit (struct test_case_struct *tc) } retval = wordexp (tc->words, &we, tc->flags); + if ((tc->flags & WRDE_NOCMD) + && (registered_forks > 0)) + { + printf ("FAILED fork called for WRDE_NOCMD\n"); + return 1; + } + if (tc->flags & WRDE_DOOFFS) start_offs = sav_we.we_offs; diff --git a/posix/wordexp.c b/posix/wordexp.c index b6b65dd..26f3a26 100644 --- a/posix/wordexp.c +++ b/posix/wordexp.c @@ -893,6 +893,10 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length, pid_t pid; int noexec = 0; + /* Do nothing if command substitution should not succeed. */ + if (flags & WRDE_NOCMD) + return WRDE_CMDSUB; + /* Don't fork() unless necessary */ if (!comm || !*comm) return 0; @@ -2082,9 +2086,6 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length, } } - if (flags & WRDE_NOCMD) - return WRDE_CMDSUB; - (*offset) += 2; return parse_comm (word, word_length, max_length, words, offset, flags, quoted? NULL : pwordexp, ifs, ifs_white); @@ -2196,9 +2197,6 @@ parse_dquote (char **word, size_t *word_length, size_t *max_length, break; case '`': - if (flags & WRDE_NOCMD) - return WRDE_CMDSUB; - ++(*offset); error = parse_backtick (word, word_length, max_length, words, offset, flags, NULL, NULL, NULL); @@ -2357,12 +2355,6 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags) break; case '`': - if (flags & WRDE_NOCMD) - { - error = WRDE_CMDSUB; - goto do_error; - } - ++words_offset; error = parse_backtick (&word, &word_length, &max_length, words, &words_offset, flags, pwordexp, ifs, diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c index 0a77c8b..08cf0a6 100644 --- a/resolv/nss_dns/dns-network.c +++ b/resolv/nss_dns/dns-network.c @@ -398,8 +398,8 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result, case BYNAME: { - char **ap = result->n_aliases++; - while (*ap != NULL) + char **ap; + for (ap = result->n_aliases; *ap != NULL; ++ap) { /* Check each alias name for being of the forms: 4.3.2.1.in-addr.arpa = net 1.2.3.4 diff --git a/stdio-common/Makefile b/stdio-common/Makefile index 5f8e534..e5e45b6 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -57,7 +57,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \ scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \ bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \ - bug25 tst-printf-round bug26 + bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 test-srcs = tst-unbputc tst-printf diff --git a/stdio-common/bug23-2.c b/stdio-common/bug23-2.c new file mode 100644 index 0000000..9e0cfe6 --- /dev/null +++ b/stdio-common/bug23-2.c @@ -0,0 +1,70 @@ +#include +#include +#include + +static const char expected[] = "\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55\ +\n\ +a\n\ +abbcd55%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; + +static int +do_test (void) +{ + char *buf = malloc (strlen (expected) + 1); + snprintf (buf, strlen (expected) + 1, + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n", + "a", "b", "c", "d", 5); + return strcmp (buf, expected) != 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdio-common/bug23-3.c b/stdio-common/bug23-3.c new file mode 100644 index 0000000..57c8cef --- /dev/null +++ b/stdio-common/bug23-3.c @@ -0,0 +1,50 @@ +#include +#include +#include + +int +do_test (void) +{ + size_t instances = 16384; +#define X0 "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d" + const char *item = "\na\nabbcd55"; +#define X3 X0 X0 X0 X0 X0 X0 X0 X0 +#define X6 X3 X3 X3 X3 X3 X3 X3 X3 +#define X9 X6 X6 X6 X6 X6 X6 X6 X6 +#define X12 X9 X9 X9 X9 X9 X9 X9 X9 +#define X14 X12 X12 X12 X12 +#define TRAILER "%%%%%%%%%%%%%%%%%%%%%%%%%%" +#define TRAILER2 TRAILER TRAILER + size_t length = instances * strlen (item) + strlen (TRAILER) + 1; + + char *buf = malloc (length + 1); + snprintf (buf, length + 1, + X14 TRAILER2 "\n", + "a", "b", "c", "d", 5); + + const char *p = buf; + size_t i; + for (i = 0; i < instances; ++i) + { + const char *expected; + for (expected = item; *expected; ++expected) + { + if (*p != *expected) + { + printf ("mismatch at offset %zu (%zu): expected %d, got %d\n", + (size_t) (p - buf), i, *expected & 0xFF, *p & 0xFF); + return 1; + } + ++p; + } + } + if (strcmp (p, TRAILER "\n") != 0) + { + printf ("mismatch at trailer: [%s]\n", p); + return 1; + } + free (buf); + return 0; +} +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdio-common/bug23-4.c b/stdio-common/bug23-4.c new file mode 100644 index 0000000..a478564 --- /dev/null +++ b/stdio-common/bug23-4.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +#define LIMIT 1000000 + +int +main (void) +{ + struct rlimit lim; + getrlimit (RLIMIT_STACK, &lim); + lim.rlim_cur = 1048576; + setrlimit (RLIMIT_STACK, &lim); + char *fmtstr = malloc (4 * LIMIT + 1); + if (fmtstr == NULL) + abort (); + char *output = malloc (LIMIT + 1); + if (output == NULL) + abort (); + for (size_t i = 0; i < LIMIT; i++) + memcpy (fmtstr + 4 * i, "%1$d", 4); + fmtstr[4 * LIMIT] = '\0'; + int ret = snprintf (output, LIMIT + 1, fmtstr, 0); + if (ret != LIMIT) + abort (); + for (size_t i = 0; i < LIMIT; i++) + if (output[i] != '0') + abort (); + return 0; +} diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index c4ff833..429a3d1 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -263,6 +263,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) /* For the argument descriptions, which may be allocated on the heap. */ void *args_malloced = NULL; + /* For positional argument handling. */ + struct printf_spec *specs; + + /* Track if we malloced the SPECS array and thus must free it. */ + bool specs_malloced = false; + /* This table maps a character into a number representing a class. In each step there is a destination label for each class. */ @@ -1679,8 +1685,8 @@ do_positional: size_t nspecs = 0; /* A more or less arbitrary start value. */ size_t nspecs_size = 32 * sizeof (struct printf_spec); - struct printf_spec *specs = alloca (nspecs_size); + specs = alloca (nspecs_size); /* The number of arguments the format string requests. This will determine the size of the array needed to store the argument attributes. */ @@ -1721,11 +1727,39 @@ do_positional: if (nspecs * sizeof (*specs) >= nspecs_size) { /* Extend the array of format specifiers. */ + if (nspecs_size * 2 < nspecs_size) + { + __set_errno (ENOMEM); + done = -1; + goto all_done; + } struct printf_spec *old = specs; - specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size); + if (__libc_use_alloca (2 * nspecs_size)) + specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size); + else + { + nspecs_size *= 2; + specs = malloc (nspecs_size); + if (specs == NULL) + { + __set_errno (ENOMEM); + specs = old; + done = -1; + goto all_done; + } + } /* Copy the old array's elements to the new space. */ memmove (specs, old, nspecs * sizeof (*specs)); + + /* If we had previously malloc'd space for SPECS, then + release it after the copy is complete. */ + if (specs_malloced) + free (old); + + /* Now set SPECS_MALLOCED if needed. */ + if (!__libc_use_alloca (nspecs_size)) + specs_malloced = true; } /* Parse the format specifier. */ @@ -2046,6 +2080,8 @@ do_positional: } all_done: + if (specs_malloced) + free (specs); if (__glibc_unlikely (args_malloced != NULL)) free (args_malloced); if (__glibc_unlikely (workstart != NULL)) diff --git a/sysdeps/aarch64/start.S b/sysdeps/aarch64/start.S index 35d603a..69b45ea 100644 --- a/sysdeps/aarch64/start.S +++ b/sysdeps/aarch64/start.S @@ -47,7 +47,6 @@ _start: /* Create an initial frame with 0 LR and FP */ mov x29, #0 mov x30, #0 - mov x29, sp /* Setup rtld_fini in argument register */ mov x5, x0 diff --git a/sysdeps/gnu/netinet/udp.h b/sysdeps/gnu/netinet/udp.h index 32159cd..8cc1c60 100644 --- a/sysdeps/gnu/netinet/udp.h +++ b/sysdeps/gnu/netinet/udp.h @@ -78,6 +78,10 @@ struct udphdr #define UDP_CORK 1 /* Never send partially complete segments. */ #define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets. */ +#define UDP_NO_CHECK6_TX 101 /* Disable sending checksum for UDP + over IPv6. */ +#define UDP_NO_CHECK6_RX 102 /* Disable accepting checksum for UDP + over IPv6. */ /* UDP encapsulation types */ #define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c index 2c04e17..a47b2ed 100644 --- a/sysdeps/unix/sysv/linux/ifaddrs.c +++ b/sysdeps/unix/sysv/linux/ifaddrs.c @@ -770,20 +770,17 @@ getifaddrs_internal (struct ifaddrs **ifap) if (cp != NULL) { - char c; unsigned int preflen; - if ((max_prefixlen > 0) && - (ifam->ifa_prefixlen > max_prefixlen)) + if (ifam->ifa_prefixlen > max_prefixlen) preflen = max_prefixlen; else preflen = ifam->ifa_prefixlen; - for (i = 0; i < ((preflen - 1) / 8); i++) + for (i = 0; i < preflen / 8; i++) *cp++ = 0xff; - c = 0xff; - c <<= ((128 - preflen) % 8); - *cp = c; + if (preflen % 8) + *cp = 0xff << (8 - preflen % 8); } } } diff --git a/sysdeps/unix/sysv/linux/mips/vfork.S b/sysdeps/unix/sysv/linux/mips/vfork.S index 80c362d..2c1a747 100644 --- a/sysdeps/unix/sysv/linux/mips/vfork.S +++ b/sysdeps/unix/sysv/linux/mips/vfork.S @@ -108,3 +108,4 @@ L(error): libc_hidden_def(__vfork) weak_alias (__vfork, vfork) +strong_alias (__vfork, __libc_vfork)