]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
glob: Prevent a stack overflow with many slashes.
authorCollin Funk <collin.funk1@gmail.com>
Sat, 11 Oct 2025 05:34:19 +0000 (22:34 -0700)
committerCollin Funk <collin.funk1@gmail.com>
Tue, 14 Oct 2025 03:24:20 +0000 (20:24 -0700)
* lib/glob.c (__glob): Strip trailing slashes before making the
recursive call.
* m4/glob.m4 (gl_GLOB): Check for the glibc bug.
* doc/posix-functions/glob.texi: Mention the bug.

ChangeLog
doc/posix-functions/glob.texi
lib/glob.c
m4/glob.m4

index 0e01db0789deea6ea04e523b506b819185955da1..cee84c0bb22cfc760ea67a993617292ad4906e1a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2025-10-13  Collin Funk  <collin.funk1@gmail.com>
+
+       glob: Prevent a stack overflow with many slashes.
+       * lib/glob.c (__glob): Strip trailing slashes before making the
+       recursive call.
+       * m4/glob.m4 (gl_GLOB): Check for the glibc bug.
+       * doc/posix-functions/glob.texi: Mention the bug.
+
 2025-10-13  Bruno Haible  <bruno@clisp.org>
 
        getline: Fix compilation error in C++ mode (regression 2025-10-10).
index c5c423bc1ad98f4a10c752265d82b6564cac428b..c74f62f9671b2906e7be281643aa5da74c84cee6 100644 (file)
@@ -20,6 +20,13 @@ glibc 2.26, AIX 7.2, HP-UX 11, Solaris 11.4.
 On platforms where @code{off_t} is a 32-bit type, this function may not
 work correctly on huge directories 2 GiB and larger.
 @xref{Large File Support}.
+@item
+This function makes a recursive call for every trailing @code{/} and
+every @code{/} following a wildcard character on some platforms, which
+can cause the stack to overflow:
+@c https://sourceware.org/PR30635
+@c https://sourceware.org/PR33537
+glibc 2.42.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index 0bd8b4237cafdb21916b2a371662f72239edf601..48f10ae0e1a4e4a2166e302cad1d731404cc5177 100644 (file)
@@ -582,6 +582,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)
index ee0320bb109a32a43ca3ccacf2d0b1a48b4e9899..563e8e4ff8e17329b52459dde262b13047e5651a 100644 (file)
@@ -1,5 +1,5 @@
 # glob.m4
-# serial 30
+# serial 31
 dnl Copyright (C) 2005-2007, 2009-2025 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -23,16 +23,45 @@ AC_DEFUN([gl_GLOB],
     esac
   else
 
-    AC_CACHE_CHECK([for GNU glob interface version 1 or 2],
-      [gl_cv_gnu_glob_interface_version_1_2],
-[     AC_COMPILE_IFELSE([AC_LANG_SOURCE(
-[[#include <gnu-versions.h>
-char a[_GNU_GLOB_INTERFACE_VERSION == 1 || _GNU_GLOB_INTERFACE_VERSION == 2 ? 1 : -1];]])],
-        [gl_cv_gnu_glob_interface_version_1_2=yes],
-        [gl_cv_gnu_glob_interface_version_1_2=no])])
-    if test "$gl_cv_gnu_glob_interface_version_1_2" = "no"; then
-      REPLACE_GLOB=1
-    fi
+    AC_CACHE_CHECK([whether glob overflows the stack with recursive calls],
+      [gl_cv_glob_overflows_stack],
+      [AC_RUN_IFELSE(
+         [AC_LANG_SOURCE([[
+            #include <stddef.h>
+            #include <stdlib.h>
+            #include <string.h>
+            #include <glob.h>
+            int
+            main (void)
+            {
+              /* Test that glob with many trailing slashes or slashes following
+                 a wildcard does not overflow the stack as it did in glibc 2.42
+                 and earlier.  */
+              char *p = malloc (10000);
+              glob_t g;
+              int res = 0;
+              if (p != NULL)
+                {
+                  memset (p, '/', 9999);
+                  p[9999] = '\0';
+                  res = glob (p, 0, NULL, &g);
+                  globfree (&g);
+                }
+              return !(res == 0);
+            }]])],
+         [gl_cv_glob_overflows_stack=no],
+         [gl_cv_glob_overflows_stack=yes],
+         [case "$host_os" in
+                               # Guess yes on glibc systems.
+            *-gnu* | gnu*)     gl_cv_glob_overflows_stack="guessing yes" ;;
+          esac
+         ])
+      ])
+
+    case $gl_cv_glob_overflows_stack in
+      *yes) REPLACE_GLOB=1 ;;
+      *) REPLACE_GLOB=0 ;;
+    esac
 
     if test $REPLACE_GLOB = 0; then
       AC_CACHE_CHECK([whether glob lists broken symlinks],