From: Collin Funk Date: Sun, 12 Oct 2025 02:01:05 +0000 (-0700) Subject: posix: Avoid a stack overflow when glob is given many slashes [BZ #30635] X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bb1d27b94a3614c7e48212a04a0b28ec66fb4c49;p=thirdparty%2Fglibc.git posix: Avoid a stack overflow when glob is given many slashes [BZ #30635] * posix/glob.c (__glob): Strip trailing slashes before the recursive call, so it is not called for every slash in the pattern. * posix/tst-glob-bz30635.c: Add two test cases that would previously segmentation fault. The first test has many trailing slashes and the second has many slashes following a wildcard character. * posix/Makefile (tests): Add the new test. Reviewed-by: Adhemerval Zanella --- diff --git a/posix/Makefile b/posix/Makefile index a36e5decd3..f6421e5379 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -288,6 +288,7 @@ tests := \ tst-fork \ tst-gai_strerror \ tst-getopt_long1 \ + tst-glob-bz30635 \ tst-glob-tilde \ tst-glob_symlinks \ tst-gnuglob \ diff --git a/posix/glob.c b/posix/glob.c index a7c7dd1ebe..0c86d26972 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -596,6 +596,10 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); } } + /* Prevent stack overflows with many trailing '/' characters. */ + for (char *p = &dirname[dirlen - 1]; + p > dirname && p[0] == '/' && p[-1] == '/'; --p) + p[0] = '\0'; int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob); if (val == 0) pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) diff --git a/posix/tst-glob-bz30635.c b/posix/tst-glob-bz30635.c new file mode 100644 index 0000000000..64e0a977f9 --- /dev/null +++ b/posix/tst-glob-bz30635.c @@ -0,0 +1,56 @@ +/* Test that glob does not overflow the stack with many slashes. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include + +/* Allocation size. */ +#define SIZE 4096 + +/* This test would cause a stack overflow on glibc 2.42 and earlier. */ +#define MAX_STACK_SIZE (8 * 1024 * 1024) + +static int +do_test (void) +{ + struct rlimit stack_limit = { MAX_STACK_SIZE, MAX_STACK_SIZE }; + TEST_VERIFY_EXIT (setrlimit (RLIMIT_STACK, &stack_limit) == 0); + glob_t g; + char *pattern = xmalloc (SIZE); + + /* Test based on BZ #30635. "/////////". */ + memset (pattern, '/', SIZE - 1); + pattern[SIZE - 1] = '\0'; + TEST_VERIFY (glob (pattern, 0, NULL, &g) == 0); + globfree (&g); + + /* Test based on BZ #33537. "/*/////sh". */ + pattern[1] = '*'; + pattern[SIZE - 3] = 's'; + pattern[SIZE - 2] = 'h'; + TEST_VERIFY (glob (pattern, 0, NULL, &g) == 0); + globfree (&g); + + return 0; +} + +#include