From a12c60564e77f66f065dce973d8a8833ecbb056a Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 2 Dec 2017 13:15:29 +0100 Subject: debian/patches/git-updates.diff: update from upstream stable branch. --- debian/patches/git-updates.diff | 1109 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 1058 insertions(+), 51 deletions(-) (limited to 'debian/patches/git-updates.diff') diff --git a/debian/patches/git-updates.diff b/debian/patches/git-updates.diff index c79e9215..9b652ee7 100644 --- a/debian/patches/git-updates.diff +++ b/debian/patches/git-updates.diff @@ -1,10 +1,107 @@ GIT update of git://sourceware.org/git/glibc.git/release/2.26/master from glibc-2.26 diff --git a/ChangeLog b/ChangeLog -index 8dbfc7eaff..0dcbe3bc69 100644 +index 8dbfc7eaff..fab886ab01 100644 --- a/ChangeLog +++ b/ChangeLog -@@ -1,3 +1,890 @@ +@@ -1,3 +1,987 @@ ++2017-11-02 Florian Weimer ++ ++ [BZ #22332] ++ * posix/tst-glob-tilde.c (do_noescape): New variable. ++ (one_test): Process it. ++ (do_test): Set do_noescape. Add unescaping test case. ++ ++2017-10-22 Paul Eggert ++ ++ [BZ #22332] ++ * posix/glob.c (__glob): Fix buffer overflow during GLOB_TILDE ++ unescaping. ++ ++2017-10-23 Wilco Dijkstra ++ ++ * malloc/malloc.c (_int_malloc): Add SINGLE_THREAD_P path. ++ ++2017-10-23 Wilco Dijkstra ++ ++ * malloc/malloc.c (__libc_malloc): Add SINGLE_THREAD_P path. ++ (__libc_realloc): Likewise. ++ (_mid_memalign): Likewise. ++ (__libc_calloc): Likewise. ++ ++2017-10-20 Wilco Dijkstra ++ ++ * malloc/malloc.c (sysdep-cancel.h): Add include. ++ ++2017-10-20 Wilco Dijkstra ++ ++ * malloc/malloc.c (_int_free): Add SINGLE_THREAD_P fast paths. ++ ++2017-10-19 Wilco Dijkstra ++ ++ * malloc/malloc.c (_int_free): Fix deadlock bug in consistency check. ++ ++2017-08-31 Florian Weimer ++ ++ * malloc/malloc.c (_int_free): Remove locked variable and related ++ asserts. ++ ++2017-08-31 Florian Weimer ++ ++ * malloc/malloc.c (top_check): Change return type to void. Remove ++ internal_function. ++ * malloc/hooks.c (top_check): Likewise. ++ (malloc_check, realloc_check, memalign_check): Adjust. ++ ++2017-08-30 Florian Weimer ++ ++ * malloc/malloc.c (ARENA_CORRUPTION_BIT, arena_is_corrupt) ++ (set_arena_corrupt): Remove definitions. ++ (mtrim): Do not check for corrupt arena. ++ * malloc/arena.c (arena_lock, reused_arena, arena_get_retry): ++ Likewise. ++ ++2017-08-30 Florian Weimer ++ ++ [BZ #21754] ++ * malloc/arena.c (TUNABLE_CALLBACK set_mallopt_check): Do not set ++ check_action. ++ (ptmalloc_init): Do not set or use check_action. ++ * malloc/hooks.c (malloc_check_get_size, realloc_check): Adjust ++ call to malloc_printerr. Remove return statement. ++ (free_check): Likewise. Remove arena unlock. ++ (top_check): Update comment. Adjust call to malloc_printerr. ++ Remove heap repair code. ++ * malloc/malloc.c (unlink): Adjust calls to malloc_printerr. ++ (DEFAULT_CHECK_ACTION, check_action): Remove definitions. ++ (sysmalloc): Adjust call to malloc_printerr. ++ (munmap_chunk, __libc_realloc): Likewise. Remove return ++ statement. ++ (_int_malloc, int_realloc): Likewise. Remove errstr variable. ++ Remove errout label and corresponding gotos. ++ (_int_free): Likewise. Remove arena unlock. ++ (do_set_mallopt_check): Do not set check_action. ++ (malloc_printerr): Adjust parameter list. Do not mark arena as ++ corrupt. ++ * manual/memory.texi (Malloc Tunable Parameters): Remove TODO ++ comment. ++ * manual/probes.texi (Memory Allocation Probes): Remove ++ memory_mallopt_check_action. ++ ++2017-08-30 Florian Weimer ++ ++ [BZ #21754] ++ * malloc/malloc.c (malloc_printerr): Always terminate the process, ++ without printing a backtrace. Do not leak any information in the ++ error message. ++ * manual/memory.texi (Heap Consistency Checking): Update. ++ * manual/tunables.texi (Memory Allocation Tunables): Likewise. ++ ++2017-11-17 Tulio Magno Quites Machado Filho ++ ++ * sysdeps/powerpc/bits/hwcap.h (PPC_FEATURE2_HTM_NO_SUSPEND): New ++ macro. ++ +2017-08-09 Andreas Schwab + + * nptl/Makefile (tests) [$(build-shared) = yes]: Add @@ -919,15 +1016,25 @@ index 9bb707c168..828a445f24 100644 # Don't try to use -lc when making libc.so itself. # Also omits crti.o and crtn.o, which we do not want diff --git a/NEWS b/NEWS -index 8295f20c0a..e7b62a8d46 100644 +index 8295f20c0a..61bffe0451 100644 --- a/NEWS +++ b/NEWS -@@ -5,6 +5,55 @@ See the end for copying conditions. +@@ -5,6 +5,74 @@ See the end for copying conditions. Please send GNU C library bug reports via using `glibc' in the "product" field. +Version 2.26.1 + ++Major new features: ++ ++* In order to support faster and safer process termination the malloc API ++ family of functions will no longer print a failure address and stack ++ backtrace after detecting heap corruption. The goal is to minimize the ++ amount of work done after corruption is detected and to avoid potential ++ security issues in continued process execution. Reducing shutdown time ++ leads to lower overall process restart latency, so there is benefit both ++ from a security and performance perspective. ++ +Security related changes: + + CVE-2009-5064: The ldd script would sometimes run the program under @@ -941,6 +1048,15 @@ index 8295f20c0a..e7b62a8d46 100644 + on the stack or the heap, depending on the length of the user name). + Reported by Tim Rühsen. + ++ CVE-2017-15671: The glob function, when invoked with GLOB_TILDE, ++ would sometimes fail to free memory allocated during ~ operator ++ processing, leading to a memory leak and, potentially, to a denial ++ of service. ++ ++ CVE-2017-15804: The glob function, when invoked with GLOB_TILDE and ++ without GLOB_NOESCAPE, could write past the end of a buffer while ++ unescaping user names. Reported by Tim Rühsen. ++ +The following bugs are resolved with this release: + + [16750] ldd: Never run file directly. @@ -1354,6 +1470,83 @@ index 3fa395b949..9e23db9343 100644 $(evaluate-test) + +$(objpfx)tst-malloc-tcache-leak: $(shared-thread-library) +diff --git a/malloc/arena.c b/malloc/arena.c +index dc14fae152..afd423240a 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -116,7 +116,7 @@ int __malloc_initialized = -1; + } while (0) + + #define arena_lock(ptr, size) do { \ +- if (ptr && !arena_is_corrupt (ptr)) \ ++ if (ptr) \ + __libc_lock_lock (ptr->mutex); \ + else \ + ptr = arena_get2 ((size), NULL); \ +@@ -215,8 +215,7 @@ void + TUNABLE_CALLBACK (set_mallopt_check) (tunable_val_t *valp) + { + int32_t value = (int32_t) valp->numval; +- do_set_mallopt_check (value); +- if (check_action != 0) ++ if (value != 0) + __malloc_check_init (); + } + +@@ -397,12 +396,8 @@ ptmalloc_init (void) + } + } + } +- if (s && s[0]) +- { +- __libc_mallopt (M_CHECK_ACTION, (int) (s[0] - '0')); +- if (check_action != 0) +- __malloc_check_init (); +- } ++ if (s && s[0] != '\0' && s[0] != '0') ++ __malloc_check_init (); + #endif + + #if HAVE_MALLOC_INIT_HOOK +@@ -837,7 +832,7 @@ reused_arena (mstate avoid_arena) + result = next_to_use; + do + { +- if (!arena_is_corrupt (result) && !__libc_lock_trylock (result->mutex)) ++ if (!__libc_lock_trylock (result->mutex)) + goto out; + + /* FIXME: This is a data race, see _int_new_arena. */ +@@ -850,18 +845,6 @@ reused_arena (mstate avoid_arena) + if (result == avoid_arena) + result = result->next; + +- /* Make sure that the arena we get is not corrupted. */ +- mstate begin = result; +- while (arena_is_corrupt (result) || result == avoid_arena) +- { +- result = result->next; +- if (result == begin) +- /* We looped around the arena list. We could not find any +- arena that was either not corrupted or not the one we +- wanted to avoid. */ +- return NULL; +- } +- + /* No arena available without contention. Wait for the next in line. */ + LIBC_PROBE (memory_arena_reuse_wait, 3, &result->mutex, result, avoid_arena); + __libc_lock_lock (result->mutex); +@@ -958,10 +941,6 @@ arena_get_retry (mstate ar_ptr, size_t bytes) + if (ar_ptr != &main_arena) + { + __libc_lock_unlock (ar_ptr->mutex); +- /* Don't touch the main arena if it is corrupt. */ +- if (arena_is_corrupt (&main_arena)) +- return NULL; +- + ar_ptr = &main_arena; + __libc_lock_lock (ar_ptr->mutex); + } diff --git a/malloc/dynarray_emplace_enlarge.c b/malloc/dynarray_emplace_enlarge.c index dfc70017ce..a15245f4cb 100644 --- a/malloc/dynarray_emplace_enlarge.c @@ -1414,11 +1607,211 @@ index e6dc9fbc68..63c981bf61 100644 void *new_array; if (list->array == scratch) { +diff --git a/malloc/hooks.c b/malloc/hooks.c +index 1d80be20d2..4398c0a017 100644 +--- a/malloc/hooks.c ++++ b/malloc/hooks.c +@@ -121,12 +121,7 @@ malloc_check_get_size (mchunkptr p) + size -= c) + { + if (c <= 0 || size < (c + 2 * SIZE_SZ)) +- { +- malloc_printerr (check_action, "malloc_check_get_size: memory corruption", +- chunk2mem (p), +- chunk_is_mmapped (p) ? NULL : arena_for_chunk (p)); +- return 0; +- } ++ malloc_printerr ("malloc_check_get_size: memory corruption"); + } + + /* chunk2mem size. */ +@@ -232,17 +227,11 @@ mem2chunk_check (void *mem, unsigned char **magic_p) + return p; + } + +-/* Check for corruption of the top chunk, and try to recover if +- necessary. */ +- +-static int +-internal_function ++/* Check for corruption of the top chunk. */ ++static void + top_check (void) + { + mchunkptr t = top (&main_arena); +- char *brk, *new_brk; +- INTERNAL_SIZE_T front_misalign, sbrk_size; +- unsigned long pagesz = GLRO (dl_pagesize); + + if (t == initial_top (&main_arena) || + (!chunk_is_mmapped (t) && +@@ -250,34 +239,9 @@ top_check (void) + prev_inuse (t) && + (!contiguous (&main_arena) || + (char *) t + chunksize (t) == mp_.sbrk_base + main_arena.system_mem))) +- return 0; +- +- malloc_printerr (check_action, "malloc: top chunk is corrupt", t, +- &main_arena); +- +- /* Try to set up a new top chunk. */ +- brk = MORECORE (0); +- front_misalign = (unsigned long) chunk2mem (brk) & MALLOC_ALIGN_MASK; +- if (front_misalign > 0) +- front_misalign = MALLOC_ALIGNMENT - front_misalign; +- sbrk_size = front_misalign + mp_.top_pad + MINSIZE; +- sbrk_size += pagesz - ((unsigned long) (brk + sbrk_size) & (pagesz - 1)); +- new_brk = (char *) (MORECORE (sbrk_size)); +- if (new_brk == (char *) (MORECORE_FAILURE)) +- { +- __set_errno (ENOMEM); +- return -1; +- } +- /* Call the `morecore' hook if necessary. */ +- void (*hook) (void) = atomic_forced_read (__after_morecore_hook); +- if (hook) +- (*hook)(); +- main_arena.system_mem = (new_brk - mp_.sbrk_base) + sbrk_size; +- +- top (&main_arena) = (mchunkptr) (brk + front_misalign); +- set_head (top (&main_arena), (sbrk_size - front_misalign) | PREV_INUSE); ++ return; + +- return 0; ++ malloc_printerr ("malloc: top chunk is corrupt"); + } + + static void * +@@ -292,7 +256,8 @@ malloc_check (size_t sz, const void *caller) + } + + __libc_lock_lock (main_arena.mutex); +- victim = (top_check () >= 0) ? _int_malloc (&main_arena, sz + 1) : NULL; ++ top_check (); ++ victim = _int_malloc (&main_arena, sz + 1); + __libc_lock_unlock (main_arena.mutex); + return mem2mem_check (victim, sz); + } +@@ -308,13 +273,7 @@ free_check (void *mem, const void *caller) + __libc_lock_lock (main_arena.mutex); + p = mem2chunk_check (mem, NULL); + if (!p) +- { +- __libc_lock_unlock (main_arena.mutex); +- +- malloc_printerr (check_action, "free(): invalid pointer", mem, +- &main_arena); +- return; +- } ++ malloc_printerr ("free(): invalid pointer"); + if (chunk_is_mmapped (p)) + { + __libc_lock_unlock (main_arena.mutex); +@@ -349,11 +308,7 @@ realloc_check (void *oldmem, size_t bytes, const void *caller) + const mchunkptr oldp = mem2chunk_check (oldmem, &magic_p); + __libc_lock_unlock (main_arena.mutex); + if (!oldp) +- { +- malloc_printerr (check_action, "realloc(): invalid pointer", oldmem, +- &main_arena); +- return malloc_check (bytes, NULL); +- } ++ malloc_printerr ("realloc(): invalid pointer"); + const INTERNAL_SIZE_T oldsize = chunksize (oldp); + + checked_request2size (bytes + 1, nb); +@@ -374,8 +329,8 @@ realloc_check (void *oldmem, size_t bytes, const void *caller) + else + { + /* Must alloc, copy, free. */ +- if (top_check () >= 0) +- newmem = _int_malloc (&main_arena, bytes + 1); ++ top_check (); ++ newmem = _int_malloc (&main_arena, bytes + 1); + if (newmem) + { + memcpy (newmem, oldmem, oldsize - 2 * SIZE_SZ); +@@ -386,12 +341,10 @@ realloc_check (void *oldmem, size_t bytes, const void *caller) + } + else + { +- if (top_check () >= 0) +- { +- INTERNAL_SIZE_T nb; +- checked_request2size (bytes + 1, nb); +- newmem = _int_realloc (&main_arena, oldp, oldsize, nb); +- } ++ top_check (); ++ INTERNAL_SIZE_T nb; ++ checked_request2size (bytes + 1, nb); ++ newmem = _int_realloc (&main_arena, oldp, oldsize, nb); + } + + /* mem2chunk_check changed the magic byte in the old chunk. +@@ -441,8 +394,8 @@ memalign_check (size_t alignment, size_t bytes, const void *caller) + } + + __libc_lock_lock (main_arena.mutex); +- mem = (top_check () >= 0) ? _int_memalign (&main_arena, alignment, bytes + 1) : +- NULL; ++ top_check (); ++ mem = _int_memalign (&main_arena, alignment, bytes + 1); + __libc_lock_unlock (main_arena.mutex); + return mem2mem_check (mem, bytes); + } diff --git a/malloc/malloc.c b/malloc/malloc.c -index 54e406bcb6..dd9f699d97 100644 +index 54e406bcb6..7783d05651 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c -@@ -1612,27 +1612,6 @@ typedef struct malloc_chunk *mfastbinptr; +@@ -243,6 +243,9 @@ + + #include + ++/* For SINGLE_THREAD_P. */ ++#include ++ + /* + Debugging: + +@@ -1019,10 +1022,10 @@ static void* _int_realloc(mstate, mchunkptr, INTERNAL_SIZE_T, + static void* _int_memalign(mstate, size_t, size_t); + static void* _mid_memalign(size_t, size_t, void *); + +-static void malloc_printerr(int action, const char *str, void *ptr, mstate av); ++static void malloc_printerr(const char *str) __attribute__ ((noreturn)); + + static void* internal_function mem2mem_check(void *p, size_t sz); +-static int internal_function top_check(void); ++static void top_check (void); + static void internal_function munmap_chunk(mchunkptr p); + #if HAVE_MREMAP + static mchunkptr internal_function mremap_chunk(mchunkptr p, size_t new_size); +@@ -1403,11 +1406,11 @@ typedef struct malloc_chunk *mbinptr; + /* Take a chunk off a bin list */ + #define unlink(AV, P, BK, FD) { \ + if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) \ +- malloc_printerr (check_action, "corrupted size vs. prev_size", P, AV); \ ++ malloc_printerr ("corrupted size vs. prev_size"); \ + FD = P->fd; \ + BK = P->bk; \ + if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \ +- malloc_printerr (check_action, "corrupted double-linked list", P, AV); \ ++ malloc_printerr ("corrupted double-linked list"); \ + else { \ + FD->bk = BK; \ + BK->fd = FD; \ +@@ -1415,9 +1418,7 @@ typedef struct malloc_chunk *mbinptr; + && __builtin_expect (P->fd_nextsize != NULL, 0)) { \ + if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) \ + || __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)) \ +- malloc_printerr (check_action, \ +- "corrupted double-linked list (not small)", \ +- P, AV); \ ++ malloc_printerr ("corrupted double-linked list (not small)"); \ + if (FD->fd_nextsize == NULL) { \ + if (P->fd_nextsize == P) \ + FD->fd_nextsize = FD->bk_nextsize = FD; \ +@@ -1612,27 +1613,6 @@ typedef struct malloc_chunk *mfastbinptr; #define FASTBIN_CONSOLIDATION_THRESHOLD (65536UL) @@ -1446,17 +1839,24 @@ index 54e406bcb6..dd9f699d97 100644 /* NONCONTIGUOUS_BIT indicates that MORECORE does not return contiguous regions. Otherwise, contiguity is exploited in merging together, -@@ -1658,6 +1637,9 @@ typedef struct malloc_chunk *mfastbinptr; - #define arena_is_corrupt(A) (((A)->flags & ARENA_CORRUPTION_BIT)) - #define set_arena_corrupt(A) ((A)->flags |= ARENA_CORRUPTION_BIT) +@@ -1649,14 +1629,8 @@ typedef struct malloc_chunk *mfastbinptr; + #define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT) + #define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT) +-/* ARENA_CORRUPTION_BIT is set if a memory corruption was detected on the +- arena. Such an arena is no longer used to allocate chunks. Chunks +- allocated in that arena before detecting corruption are not freed. */ +- +-#define ARENA_CORRUPTION_BIT (4U) +- +-#define arena_is_corrupt(A) (((A)->flags & ARENA_CORRUPTION_BIT)) +-#define set_arena_corrupt(A) ((A)->flags |= ARENA_CORRUPTION_BIT) +/* Maximum size of memory handled in fastbins. */ +static INTERNAL_SIZE_T global_max_fast; -+ + /* Set value of max_fast. - Use impossibly small value if 0. -@@ -1668,13 +1650,36 @@ typedef struct malloc_chunk *mfastbinptr; +@@ -1668,13 +1642,36 @@ typedef struct malloc_chunk *mfastbinptr; #define set_max_fast(s) \ global_max_fast = (((s) == 0) \ ? SMALLBIN_WIDTH : ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK)) @@ -1494,7 +1894,7 @@ index 54e406bcb6..dd9f699d97 100644 struct malloc_state { /* Serialize access. */ -@@ -1683,6 +1688,10 @@ struct malloc_state +@@ -1683,6 +1680,10 @@ struct malloc_state /* Flags (formerly in max_fast). */ int flags; @@ -1505,7 +1905,7 @@ index 54e406bcb6..dd9f699d97 100644 /* Fastbins */ mfastbinptr fastbinsY[NFASTBINS]; -@@ -1797,9 +1806,6 @@ static struct malloc_par mp_ = +@@ -1797,9 +1798,6 @@ static struct malloc_par mp_ = #endif }; @@ -1515,7 +1915,7 @@ index 54e406bcb6..dd9f699d97 100644 /* Initialize a malloc_state struct. -@@ -1829,7 +1835,7 @@ malloc_init_state (mstate av) +@@ -1829,7 +1827,7 @@ malloc_init_state (mstate av) set_noncontiguous (av); if (av == &main_arena) set_max_fast (DEFAULT_MXFAST); @@ -1524,7 +1924,23 @@ index 54e406bcb6..dd9f699d97 100644 av->top = initial_top (av); } -@@ -2194,11 +2200,6 @@ do_check_malloc_state (mstate av) +@@ -1880,15 +1878,6 @@ void *weak_variable (*__memalign_hook) + void weak_variable (*__after_morecore_hook) (void) = NULL; + + +-/* ---------------- Error behavior ------------------------------------ */ +- +-#ifndef DEFAULT_CHECK_ACTION +-# define DEFAULT_CHECK_ACTION 3 +-#endif +- +-static int check_action = DEFAULT_CHECK_ACTION; +- +- + /* ------------------ Testing support ----------------------------------*/ + + static int perturb_byte; +@@ -2194,11 +2183,6 @@ do_check_malloc_state (mstate av) } } @@ -1536,7 +1952,34 @@ index 54e406bcb6..dd9f699d97 100644 /* check normal bins */ for (i = 1; i < NBINS; ++i) { -@@ -2940,12 +2941,12 @@ typedef struct tcache_perthread_struct +@@ -2566,11 +2550,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + set_head (old_top, (size + old_size) | PREV_INUSE); + + else if (contiguous (av) && old_size && brk < old_end) +- { +- /* Oops! Someone else killed our space.. Can't touch anything. */ +- malloc_printerr (3, "break adjusted to free malloc space", brk, +- av); +- } ++ /* Oops! Someone else killed our space.. Can't touch anything. */ ++ malloc_printerr ("break adjusted to free malloc space"); + + /* + Otherwise, make adjustments: +@@ -2861,11 +2842,7 @@ munmap_chunk (mchunkptr p) + (in the moment at least) so we combine the two values into one before + the bit test. */ + if (__builtin_expect (((block | total_size) & (GLRO (dl_pagesize) - 1)) != 0, 0)) +- { +- malloc_printerr (check_action, "munmap_chunk(): invalid pointer", +- chunk2mem (p), NULL); +- return; +- } ++ malloc_printerr ("munmap_chunk(): invalid pointer"); + + atomic_decrement (&mp_.n_mmaps); + atomic_add (&mp_.mmapped_mem, -total_size); +@@ -2940,12 +2917,12 @@ typedef struct tcache_perthread_struct tcache_entry *entries[TCACHE_MAX_BINS]; } tcache_perthread_struct; @@ -1551,7 +1994,7 @@ index 54e406bcb6..dd9f699d97 100644 tcache_put (mchunkptr chunk, size_t tc_idx) { tcache_entry *e = (tcache_entry *) chunk2mem (chunk); -@@ -2957,7 +2958,7 @@ tcache_put (mchunkptr chunk, size_t tc_idx) +@@ -2957,7 +2934,7 @@ tcache_put (mchunkptr chunk, size_t tc_idx) /* Caller must ensure that we know tc_idx is valid and there's available chunks to remove. */ @@ -1560,7 +2003,7 @@ index 54e406bcb6..dd9f699d97 100644 tcache_get (size_t tc_idx) { tcache_entry *e = tcache->entries[tc_idx]; -@@ -2977,8 +2978,12 @@ tcache_thread_freeres (void) +@@ -2977,8 +2954,12 @@ tcache_thread_freeres (void) if (!tcache) return; @@ -1573,7 +2016,7 @@ index 54e406bcb6..dd9f699d97 100644 for (i = 0; i < TCACHE_MAX_BINS; ++i) { while (tcache_tmp->entries[i]) -@@ -2990,8 +2995,6 @@ tcache_thread_freeres (void) +@@ -2990,8 +2971,6 @@ tcache_thread_freeres (void) } __libc_free (tcache_tmp); @@ -1582,7 +2025,215 @@ index 54e406bcb6..dd9f699d97 100644 } text_set_element (__libc_thread_subfreeres, tcache_thread_freeres); -@@ -3687,7 +3690,7 @@ _int_malloc (mstate av, size_t bytes) +@@ -3066,6 +3045,14 @@ __libc_malloc (size_t bytes) + DIAG_POP_NEEDS_COMMENT; + #endif + ++ if (SINGLE_THREAD_P) ++ { ++ victim = _int_malloc (&main_arena, bytes); ++ assert (!victim || chunk_is_mmapped (mem2chunk (victim)) || ++ &main_arena == arena_for_chunk (mem2chunk (victim))); ++ return victim; ++ } ++ + arena_get (ar_ptr, bytes); + + victim = _int_malloc (ar_ptr, bytes); +@@ -3177,11 +3164,7 @@ __libc_realloc (void *oldmem, size_t bytes) + if ((__builtin_expect ((uintptr_t) oldp > (uintptr_t) -oldsize, 0) + || __builtin_expect (misaligned_chunk (oldp), 0)) + && !DUMPED_MAIN_ARENA_CHUNK (oldp)) +- { +- malloc_printerr (check_action, "realloc(): invalid pointer", oldmem, +- ar_ptr); +- return NULL; +- } ++ malloc_printerr ("realloc(): invalid pointer"); + + checked_request2size (bytes, nb); + +@@ -3226,6 +3209,15 @@ __libc_realloc (void *oldmem, size_t bytes) + return newmem; + } + ++ if (SINGLE_THREAD_P) ++ { ++ newp = _int_realloc (ar_ptr, oldp, oldsize, nb); ++ assert (!newp || chunk_is_mmapped (mem2chunk (newp)) || ++ ar_ptr == arena_for_chunk (mem2chunk (newp))); ++ ++ return newp; ++ } ++ + __libc_lock_lock (ar_ptr->mutex); + + newp = _int_realloc (ar_ptr, oldp, oldsize, nb); +@@ -3301,6 +3293,15 @@ _mid_memalign (size_t alignment, size_t bytes, void *address) + alignment = a; + } + ++ if (SINGLE_THREAD_P) ++ { ++ p = _int_memalign (&main_arena, alignment, bytes); ++ assert (!p || chunk_is_mmapped (mem2chunk (p)) || ++ &main_arena == arena_for_chunk (mem2chunk (p))); ++ ++ return p; ++ } ++ + arena_get (ar_ptr, bytes + alignment + MINSIZE); + + p = _int_memalign (ar_ptr, alignment, bytes); +@@ -3393,7 +3394,11 @@ __libc_calloc (size_t n, size_t elem_size) + + MAYBE_INIT_TCACHE (); + +- arena_get (av, sz); ++ if (SINGLE_THREAD_P) ++ av = &main_arena; ++ else ++ arena_get (av, sz); ++ + if (av) + { + /* Check if we hand out the top chunk, in which case there may be no +@@ -3423,19 +3428,21 @@ __libc_calloc (size_t n, size_t elem_size) + } + mem = _int_malloc (av, sz); + +- + assert (!mem || chunk_is_mmapped (mem2chunk (mem)) || + av == arena_for_chunk (mem2chunk (mem))); + +- if (mem == 0 && av != NULL) ++ if (!SINGLE_THREAD_P) + { +- LIBC_PROBE (memory_calloc_retry, 1, sz); +- av = arena_get_retry (av, sz); +- mem = _int_malloc (av, sz); +- } ++ if (mem == 0 && av != NULL) ++ { ++ LIBC_PROBE (memory_calloc_retry, 1, sz); ++ av = arena_get_retry (av, sz); ++ mem = _int_malloc (av, sz); ++ } + +- if (av != NULL) +- __libc_lock_unlock (av->mutex); ++ if (av != NULL) ++ __libc_lock_unlock (av->mutex); ++ } + + /* Allocation failed even after a retry. */ + if (mem == 0) +@@ -3527,8 +3534,6 @@ _int_malloc (mstate av, size_t bytes) + size_t tcache_unsorted_count; /* count of unsorted chunks processed */ + #endif + +- const char *errstr = NULL; +- + /* + Convert request size to internal form by adding SIZE_SZ bytes + overhead plus possibly more to obtain necessary alignment and/or +@@ -3570,42 +3575,50 @@ _int_malloc (mstate av, size_t bytes) + { + idx = fastbin_index (nb); + mfastbinptr *fb = &fastbin (av, idx); +- mchunkptr pp = *fb; +- REMOVE_FB (fb, victim, pp); +- if (victim != 0) +- { +- if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0)) +- { +- errstr = "malloc(): memory corruption (fast)"; +- errout: +- malloc_printerr (check_action, errstr, chunk2mem (victim), av); +- return NULL; +- } +- check_remalloced_chunk (av, victim, nb); +-#if USE_TCACHE +- /* While we're here, if we see other chunks of the same size, +- stash them in the tcache. */ +- size_t tc_idx = csize2tidx (nb); +- if (tcache && tc_idx < mp_.tcache_bins) +- { +- mchunkptr tc_victim; ++ mchunkptr pp; ++ victim = *fb; + +- /* While bin not empty and tcache not full, copy chunks over. */ +- while (tcache->counts[tc_idx] < mp_.tcache_count +- && (pp = *fb) != NULL) ++ if (victim != NULL) ++ { ++ if (SINGLE_THREAD_P) ++ *fb = victim->fd; ++ else ++ REMOVE_FB (fb, pp, victim); ++ if (__glibc_likely (victim != NULL)) ++ { ++ size_t victim_idx = fastbin_index (chunksize (victim)); ++ if (__builtin_expect (victim_idx != idx, 0)) ++ malloc_printerr ("malloc(): memory corruption (fast)"); ++ check_remalloced_chunk (av, victim, nb); ++#if USE_TCACHE ++ /* While we're here, if we see other chunks of the same size, ++ stash them in the tcache. */ ++ size_t tc_idx = csize2tidx (nb); ++ if (tcache && tc_idx < mp_.tcache_bins) + { +- REMOVE_FB (fb, tc_victim, pp); +- if (tc_victim != 0) ++ mchunkptr tc_victim; ++ ++ /* While bin not empty and tcache not full, copy chunks. */ ++ while (tcache->counts[tc_idx] < mp_.tcache_count ++ && (tc_victim = *fb) != NULL) + { ++ if (SINGLE_THREAD_P) ++ *fb = tc_victim->fd; ++ else ++ { ++ REMOVE_FB (fb, pp, tc_victim); ++ if (__glibc_unlikely (tc_victim == NULL)) ++ break; ++ } + tcache_put (tc_victim, tc_idx); +- } ++ } + } +- } + #endif +- void *p = chunk2mem (victim); +- alloc_perturb (p, bytes); +- return p; +- } ++ void *p = chunk2mem (victim); ++ alloc_perturb (p, bytes); ++ return p; ++ } ++ } + } + + /* +@@ -3628,11 +3641,9 @@ _int_malloc (mstate av, size_t bytes) + else + { + bck = victim->bk; +- if (__glibc_unlikely (bck->fd != victim)) +- { +- errstr = "malloc(): smallbin double linked list corrupted"; +- goto errout; +- } ++ if (__glibc_unlikely (bck->fd != victim)) ++ malloc_printerr ++ ("malloc(): smallbin double linked list corrupted"); + set_inuse_bit_at_offset (victim, nb); + bin->bk = bck; + bck->fd = bin; +@@ -3687,7 +3698,7 @@ _int_malloc (mstate av, size_t bytes) else { idx = largebin_index (nb); @@ -1591,7 +2242,45 @@ index 54e406bcb6..dd9f699d97 100644 malloc_consolidate (av); } -@@ -4102,7 +4105,7 @@ _int_malloc (mstate av, size_t bytes) +@@ -3723,8 +3734,7 @@ _int_malloc (mstate av, size_t bytes) + if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0) + || __builtin_expect (chunksize_nomask (victim) + > av->system_mem, 0)) +- malloc_printerr (check_action, "malloc(): memory corruption", +- chunk2mem (victim), av); ++ malloc_printerr ("malloc(): memory corruption"); + size = chunksize (victim); + + /* +@@ -3929,11 +3939,8 @@ _int_malloc (mstate av, size_t bytes) + have to perform a complete insert here. */ + bck = unsorted_chunks (av); + fwd = bck->fd; +- if (__glibc_unlikely (fwd->bk != bck)) +- { +- errstr = "malloc(): corrupted unsorted chunks"; +- goto errout; +- } ++ if (__glibc_unlikely (fwd->bk != bck)) ++ malloc_printerr ("malloc(): corrupted unsorted chunks"); + remainder->bk = bck; + remainder->fd = fwd; + bck->fd = remainder; +@@ -4036,11 +4043,8 @@ _int_malloc (mstate av, size_t bytes) + have to perform a complete insert here. */ + bck = unsorted_chunks (av); + fwd = bck->fd; +- if (__glibc_unlikely (fwd->bk != bck)) +- { +- errstr = "malloc(): corrupted unsorted chunks 2"; +- goto errout; +- } ++ if (__glibc_unlikely (fwd->bk != bck)) ++ malloc_printerr ("malloc(): corrupted unsorted chunks 2"); + remainder->bk = bck; + remainder->fd = fwd; + bck->fd = remainder; +@@ -4102,7 +4106,7 @@ _int_malloc (mstate av, size_t bytes) /* When we are using atomic ops to free fast chunks we can get here for all block sizes. */ @@ -1600,7 +2289,74 @@ index 54e406bcb6..dd9f699d97 100644 { malloc_consolidate (av); /* restore original bin index */ -@@ -4228,7 +4231,7 @@ _int_free (mstate av, mchunkptr p, int have_lock) +@@ -4141,9 +4145,6 @@ _int_free (mstate av, mchunkptr p, int have_lock) + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + +- const char *errstr = NULL; +- int locked = 0; +- + size = chunksize (p); + + /* Little security check which won't hurt performance: the +@@ -4152,21 +4153,11 @@ _int_free (mstate av, mchunkptr p, int have_lock) + here by accident or by "design" from some intruder. */ + if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0) + || __builtin_expect (misaligned_chunk (p), 0)) +- { +- errstr = "free(): invalid pointer"; +- errout: +- if (!have_lock && locked) +- __libc_lock_unlock (av->mutex); +- malloc_printerr (check_action, errstr, chunk2mem (p), av); +- return; +- } ++ malloc_printerr ("free(): invalid pointer"); + /* We know that each chunk is at least MINSIZE bytes in size or a + multiple of MALLOC_ALIGNMENT. */ + if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size))) +- { +- errstr = "free(): invalid size"; +- goto errout; +- } ++ malloc_printerr ("free(): invalid size"); + + check_inuse_chunk(av, p); + +@@ -4205,60 +4196,59 @@ _int_free (mstate av, mchunkptr p, int have_lock) + || __builtin_expect (chunksize (chunk_at_offset (p, size)) + >= av->system_mem, 0)) + { ++ bool fail = true; + /* We might not have a lock at this point and concurrent modifications +- of system_mem might have let to a false positive. Redo the test +- after getting the lock. */ +- if (have_lock +- || ({ assert (locked == 0); +- __libc_lock_lock (av->mutex); +- locked = 1; +- chunksize_nomask (chunk_at_offset (p, size)) <= 2 * SIZE_SZ +- || chunksize (chunk_at_offset (p, size)) >= av->system_mem; +- })) +- { +- errstr = "free(): invalid next size (fast)"; +- goto errout; +- } +- if (! have_lock) ++ of system_mem might result in a false positive. Redo the test after ++ getting the lock. */ ++ if (!have_lock) + { ++ __libc_lock_lock (av->mutex); ++ fail = (chunksize_nomask (chunk_at_offset (p, size)) <= 2 * SIZE_SZ ++ || chunksize (chunk_at_offset (p, size)) >= av->system_mem); + __libc_lock_unlock (av->mutex); +- locked = 0; + } ++ ++ if (fail) ++ malloc_printerr ("free(): invalid next size (fast)"); + } free_perturb (chunk2mem(p), size - 2 * SIZE_SZ); @@ -1609,7 +2365,128 @@ index 54e406bcb6..dd9f699d97 100644 unsigned int idx = fastbin_index(size); fb = &fastbin (av, idx); -@@ -4379,7 +4382,7 @@ _int_free (mstate av, mchunkptr p, int have_lock) + /* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */ + mchunkptr old = *fb, old2; +- unsigned int old_idx = ~0u; +- do +- { +- /* Check that the top of the bin is not the record we are going to add +- (i.e., double free). */ +- if (__builtin_expect (old == p, 0)) +- { +- errstr = "double free or corruption (fasttop)"; +- goto errout; +- } +- /* Check that size of fastbin chunk at the top is the same as +- size of the chunk that we are adding. We can dereference OLD +- only if we have the lock, otherwise it might have already been +- deallocated. See use of OLD_IDX below for the actual check. */ +- if (have_lock && old != NULL) +- old_idx = fastbin_index(chunksize(old)); +- p->fd = old2 = old; +- } +- while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2)) != old2); + +- if (have_lock && old != NULL && __builtin_expect (old_idx != idx, 0)) ++ if (SINGLE_THREAD_P) + { +- errstr = "invalid fastbin entry (free)"; +- goto errout; ++ /* Check that the top of the bin is not the record we are going to ++ add (i.e., double free). */ ++ if (__builtin_expect (old == p, 0)) ++ malloc_printerr ("double free or corruption (fasttop)"); ++ p->fd = old; ++ *fb = p; + } ++ else ++ do ++ { ++ /* Check that the top of the bin is not the record we are going to ++ add (i.e., double free). */ ++ if (__builtin_expect (old == p, 0)) ++ malloc_printerr ("double free or corruption (fasttop)"); ++ p->fd = old2 = old; ++ } ++ while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2)) ++ != old2); ++ ++ /* Check that size of fastbin chunk at the top is the same as ++ size of the chunk that we are adding. We can dereference OLD ++ only if we have the lock, otherwise it might have already been ++ allocated again. */ ++ if (have_lock && old != NULL ++ && __builtin_expect (fastbin_index (chunksize (old)) != idx, 0)) ++ malloc_printerr ("invalid fastbin entry (free)"); + } + + /* +@@ -4266,42 +4256,33 @@ _int_free (mstate av, mchunkptr p, int have_lock) + */ + + else if (!chunk_is_mmapped(p)) { +- if (! have_lock) { ++ ++ /* If we're single-threaded, don't lock the arena. */ ++ if (SINGLE_THREAD_P) ++ have_lock = true; ++ ++ if (!have_lock) + __libc_lock_lock (av->mutex); +- locked = 1; +- } + + nextchunk = chunk_at_offset(p, size); + + /* Lightweight tests: check whether the block is already the + top block. */ + if (__glibc_unlikely (p == av->top)) +- { +- errstr = "double free or corruption (top)"; +- goto errout; +- } ++ malloc_printerr ("double free or corruption (top)"); + /* Or whether the next chunk is beyond the boundaries of the arena. */ + if (__builtin_expect (contiguous (av) + && (char *) nextchunk + >= ((char *) av->top + chunksize(av->top)), 0)) +- { +- errstr = "double free or corruption (out)"; +- goto errout; +- } ++ malloc_printerr ("double free or corruption (out)"); + /* Or whether the block is actually not marked used. */ + if (__glibc_unlikely (!prev_inuse(nextchunk))) +- { +- errstr = "double free or corruption (!prev)"; +- goto errout; +- } ++ malloc_printerr ("double free or corruption (!prev)"); + + nextsize = chunksize(nextchunk); + if (__builtin_expect (chunksize_nomask (nextchunk) <= 2 * SIZE_SZ, 0) + || __builtin_expect (nextsize >= av->system_mem, 0)) +- { +- errstr = "free(): invalid next size (normal)"; +- goto errout; +- } ++ malloc_printerr ("free(): invalid next size (normal)"); + + free_perturb (chunk2mem(p), size - 2 * SIZE_SZ); + +@@ -4333,10 +4314,7 @@ _int_free (mstate av, mchunkptr p, int have_lock) + bck = unsorted_chunks(av); + fwd = bck->fd; + if (__glibc_unlikely (fwd->bk != bck)) +- { +- errstr = "free(): corrupted unsorted chunks"; +- goto errout; +- } ++ malloc_printerr ("free(): corrupted unsorted chunks"); + p->fd = fwd; + p->bk = bck; + if (!in_smallbin_range(size)) +@@ -4379,7 +4357,7 @@ _int_free (mstate av, mchunkptr p, int have_lock) */ if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { @@ -1618,7 +2495,19 @@ index 54e406bcb6..dd9f699d97 100644 malloc_consolidate(av); if (av == &main_arena) { -@@ -4450,7 +4453,7 @@ static void malloc_consolidate(mstate av) +@@ -4398,10 +4376,8 @@ _int_free (mstate av, mchunkptr p, int have_lock) + } + } + +- if (! have_lock) { +- assert (locked); ++ if (!have_lock) + __libc_lock_unlock (av->mutex); +- } + } + /* + If the chunk was allocated via mmap, release via munmap(). +@@ -4450,7 +4426,7 @@ static void malloc_consolidate(mstate av) */ if (get_max_fast () != 0) { @@ -1627,6 +2516,93 @@ index 54e406bcb6..dd9f699d97 100644 unsorted_bin = unsorted_chunks(av); +@@ -4549,17 +4525,10 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + INTERNAL_SIZE_T* s; /* copy source */ + INTERNAL_SIZE_T* d; /* copy destination */ + +- const char *errstr = NULL; +- + /* oldmem size */ + if (__builtin_expect (chunksize_nomask (oldp) <= 2 * SIZE_SZ, 0) + || __builtin_expect (oldsize >= av->system_mem, 0)) +- { +- errstr = "realloc(): invalid old size"; +- errout: +- malloc_printerr (check_action, errstr, chunk2mem (oldp), av); +- return NULL; +- } ++ malloc_printerr ("realloc(): invalid old size"); + + check_inuse_chunk (av, oldp); + +@@ -4570,10 +4539,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + INTERNAL_SIZE_T nextsize = chunksize (next); + if (__builtin_expect (chunksize_nomask (next) <= 2 * SIZE_SZ, 0) + || __builtin_expect (nextsize >= av->system_mem, 0)) +- { +- errstr = "realloc(): invalid next size"; +- goto errout; +- } ++ malloc_printerr ("realloc(): invalid next size"); + + if ((unsigned long) (oldsize) >= (unsigned long) (nb)) + { +@@ -4798,10 +4764,6 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) + static int + mtrim (mstate av, size_t pad) + { +- /* Don't touch corrupt arenas. */ +- if (arena_is_corrupt (av)) +- return 0; +- + /* Ensure initialization/consolidation */ + malloc_consolidate (av); + +@@ -5113,8 +5075,6 @@ static inline int + __always_inline + do_set_mallopt_check (int32_t value) + { +- LIBC_PROBE (memory_mallopt_check_action, 2, value, check_action); +- check_action = value; + return 1; + } + +@@ -5388,32 +5348,10 @@ libc_hidden_def (__libc_mallopt) + extern char **__libc_argv attribute_hidden; + + static void +-malloc_printerr (int action, const char *str, void *ptr, mstate ar_ptr) ++malloc_printerr (const char *str) + { +- /* Avoid using this arena in future. We do not attempt to synchronize this +- with anything else because we minimally want to ensure that __libc_message +- gets its resources safely without stumbling on the current corruption. */ +- if (ar_ptr) +- set_arena_corrupt (ar_ptr); +- +- if ((action & 5) == 5) +- __libc_message ((action & 2) ? (do_abort | do_backtrace) : do_message, +- "%s\n", str); +- else if (action & 1) +- { +- char buf[2 * sizeof (uintptr_t) + 1]; +- +- buf[sizeof (buf) - 1] = '\0'; +- char *cp = _itoa_word ((uintptr_t) ptr, &buf[sizeof (buf) - 1], 16, 0); +- while (cp > buf) +- *--cp = '0'; +- +- __libc_message ((action & 2) ? (do_abort | do_backtrace) : do_message, +- "*** Error in `%s': %s: 0x%s ***\n", +- __libc_argv[0] ? : "", str, cp); +- } +- else if (action & 2) +- abort (); ++ __libc_message (do_abort, "%s\n", str); ++ __builtin_unreachable (); + } + + /* We need a wrapper function for one of the additions of POSIX. */ diff --git a/malloc/tst-dynarray.c b/malloc/tst-dynarray.c index 2206d75e31..d11f7bb8a3 100644 --- a/malloc/tst-dynarray.c @@ -6532,7 +7508,7 @@ index 0000000000..107c1f09e9 + ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \ + & ~ (FLEXALIGNOF (type) - 1)) diff --git a/posix/glob.c b/posix/glob.c -index c653809118..c761c0861d 100644 +index c653809118..b2273ea7bc 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -15,7 +15,7 @@ @@ -7234,6 +8210,20 @@ index c653809118..c761c0861d 100644 newp = alloca_account (end_name - dirname, alloca_used); else { +@@ -823,11 +850,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), + char *p = mempcpy (newp, dirname + 1, + unescape - dirname - 1); + char *q = unescape; +- while (*q != '\0') ++ while (q != end_name) + { + if (*q == '\\') + { +- if (q[1] == '\0') ++ if (q + 1 == end_name) + { + /* "~fo\\o\\" unescape to user_name "foo\\", + but "~fo\\o\\/" unescape to user_name @@ -843,7 +870,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), *p = '\0'; } @@ -8193,11 +9183,11 @@ index 0000000000..c9f8908a4e +libc_hidden_def (globfree64) diff --git a/posix/tst-glob-tilde.c b/posix/tst-glob-tilde.c new file mode 100644 -index 0000000000..9518b4a6f8 +index 0000000000..6886f4371f --- /dev/null +++ b/posix/tst-glob-tilde.c -@@ -0,0 +1,136 @@ -+/* Check for GLOB_TIDLE heap allocation issues (bug 22320, bug 22325). +@@ -0,0 +1,143 @@ ++/* Check for GLOB_TIDLE heap allocation issues (bugs 22320, 22325, 22332). + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + @@ -8233,6 +9223,9 @@ index 0000000000..9518b4a6f8 +/* Flag which indicates whether to pass the GLOB_MARK flag. */ +static int do_mark; + ++/* Flag which indicates whether to pass the GLOB_NOESCAPE flag. */ ++static int do_noescape; ++ +static void +one_test (const char *prefix, const char *middle, const char *suffix) +{ @@ -8244,6 +9237,8 @@ index 0000000000..9518b4a6f8 + flags |= GLOB_NOCHECK; + if (do_mark) + flags |= GLOB_MARK; ++ if (do_noescape) ++ flags |= GLOB_NOESCAPE; + glob_t gl; + /* This glob call might result in crashes or memory leaks. */ + if (glob (pattern, flags, NULL, &gl) == 0) @@ -8304,28 +9299,30 @@ index 0000000000..9518b4a6f8 + for (do_onlydir = 0; do_onlydir < 2; ++do_onlydir) + for (do_nocheck = 0; do_nocheck < 2; ++do_nocheck) + for (do_mark = 0; do_mark < 2; ++do_mark) -+ for (int base_idx = 0; base_sizes[base_idx] >= 0; ++base_idx) -+ { -+ for (int size_skew = -max_size_skew; size_skew <= max_size_skew; -+ ++size_skew) -+ { -+ int size = base_sizes[base_idx] + size_skew; -+ if (size < 0) -+ continue; -+ -+ const char *user_name = repeating_string (size); -+ one_test ("~", user_name, "/a/b"); -+ } -+ -+ const char *user_name = repeating_string (base_sizes[base_idx]); -+ one_test ("~", user_name, ""); -+ one_test ("~", user_name, "/"); -+ one_test ("~", user_name, "/a"); -+ one_test ("~", user_name, "/*/*"); -+ one_test ("~", user_name, "\\/"); -+ one_test ("/~", user_name, ""); -+ one_test ("*/~", user_name, "/a/b"); -+ } ++ for (do_noescape = 0; do_noescape < 2; ++do_noescape) ++ for (int base_idx = 0; base_sizes[base_idx] >= 0; ++base_idx) ++ { ++ for (int size_skew = -max_size_skew; size_skew <= max_size_skew; ++ ++size_skew) ++ { ++ int size = base_sizes[base_idx] + size_skew; ++ if (size < 0) ++ continue; ++ ++ const char *user_name = repeating_string (size); ++ one_test ("~", user_name, "/a/b"); ++ one_test ("~", user_name, "x\\x\\x////x\\a"); ++ } ++ ++ const char *user_name = repeating_string (base_sizes[base_idx]); ++ one_test ("~", user_name, ""); ++ one_test ("~", user_name, "/"); ++ one_test ("~", user_name, "/a"); ++ one_test ("~", user_name, "/*/*"); ++ one_test ("~", user_name, "\\/"); ++ one_test ("/~", user_name, ""); ++ one_test ("*/~", user_name, "/a/b"); ++ } + + free (repeat); + @@ -15138,6 +16135,16 @@ index 0d9206bec4..6aa683b03f 100644 ifneq (no,$(multi-arch)) tests-static += tst-tlsifunc-static +diff --git a/sysdeps/powerpc/bits/hwcap.h b/sysdeps/powerpc/bits/hwcap.h +index dfc71c29bb..0668ca041e 100644 +--- a/sysdeps/powerpc/bits/hwcap.h ++++ b/sysdeps/powerpc/bits/hwcap.h +@@ -72,3 +72,5 @@ + 128-bit */ + #define PPC_FEATURE2_DARN 0x00200000 /* darn instruction. */ + #define PPC_FEATURE2_SCV 0x00100000 /* scv syscall. */ ++#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 /* TM without suspended ++ state. */ diff --git a/sysdeps/powerpc/fpu/math_private.h b/sysdeps/powerpc/fpu/math_private.h index d8fd4923ac..396fd0562e 100644 --- a/sysdeps/powerpc/fpu/math_private.h -- cgit v1.2.3