Skip to content

Conversation

@sthibaul
Copy link
Contributor

@sthibaul sthibaul commented Nov 4, 2025

e.g.

glob_t g;
memset(&g, 0, sizeof(g);
g.gl_offs = 1;
glob("*", GLOB_DOOFFS, NULL, &g);

will reserve one NULL entry at the beginning of g.gl_pathv, in addition to the gl.gl_pathc results.

@llvmbot
Copy link
Member

llvmbot commented Nov 4, 2025

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Samuel Thibault (sthibaul)

Changes

e.g.

glob_t g;
memset(&g, 0, sizeof(g);
g.gl_offs = 1;
glob("*", GLOB_DOOFFS, NULL, &g);

will reserve one NULL entry at the beginning of g.gl_pathv, in addition to the gl.gl_pathc results.


Full diff: https://github.com/llvm/llvm-project/pull/166468.diff

1 Files Affected:

  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc (+11-6)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 24a8a2d4dc55b..8bb03f6d251fb 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -2409,13 +2409,18 @@ INTERCEPTOR(int, timespec_get, struct __sanitizer_timespec *ts, int base) {
 #endif
 
 #if SANITIZER_INTERCEPT_GLOB
-static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
+static void unpoison_glob_t(void *ctx, int flags, __sanitizer_glob_t *pglob) {
+  SIZE_T offs;
   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
+  if (flags & GLOB_DOOFFS)
+    offs = pglob->gl_offs;
+  else
+    offs = 0;
   // +1 for NULL pointer at the end.
   if (pglob->gl_pathv)
     COMMON_INTERCEPTOR_WRITE_RANGE(
-        ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
-  for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
+        ctx, pglob->gl_pathv, (offs + pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
+  for (SIZE_T i = offs; i < offs + pglob->gl_pathc; ++i) {
     char *p = pglob->gl_pathv[i];
     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, internal_strlen(p) + 1);
   }
@@ -2429,7 +2434,7 @@ INTERCEPTOR(int, glob, const char *pattern, int flags,
   COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
   COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
   int res = REAL(glob)(pattern, flags, errfunc, pglob);
-  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
+  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, flags, pglob);
   return res;
 }
 #else
@@ -2493,7 +2498,7 @@ INTERCEPTOR(int, glob, const char *pattern, int flags,
     Swap(pglob->gl_stat, glob_copy.gl_stat);
   }
   pglob_copy = 0;
-  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
+  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, flags, pglob);
   return res;
 }
 #endif  // SANITIZER_SOLARIS
@@ -2529,7 +2534,7 @@ INTERCEPTOR(int, glob64, const char *pattern, int flags,
     Swap(pglob->gl_stat, glob_copy.gl_stat);
   }
   pglob_copy = 0;
-  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
+  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, flags, pglob);
   return res;
 }
 #define INIT_GLOB64                \

@github-actions
Copy link

github-actions bot commented Nov 4, 2025

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff origin/main HEAD --extensions h,inc,cpp -- compiler-rt/test/sanitizer_common/TestCases/Posix/glob.cpp compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h --diff_from_common_commit

⚠️
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing origin/main to the base branch/commit you want to compare against.
⚠️

View the diff from clang-format here.
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 7729dde59..13ea1f15c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -2486,7 +2486,7 @@ static void unpoison_glob_t(void* ctx, int flags, __sanitizer_glob_t* pglob) {
   }
 }
 
-#if SANITIZER_SOLARIS
+#  if SANITIZER_SOLARIS
 INTERCEPTOR(int, glob, const char *pattern, int flags,
             int (*errfunc)(const char *epath, int eerrno),
             __sanitizer_glob_t *pglob) {

@sthibaul sthibaul force-pushed the glob_offs branch 2 times, most recently from 8a63aff to 715f002 Compare November 4, 2025 23:50
@sthibaul
Copy link
Contributor Author

sthibaul commented Nov 4, 2025

Mmm, the formatting test asks me to change a line which my patch doesn't touch at all...

Copy link
Collaborator

@vitalybuka vitalybuka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for that patch!
Would it be possible to add a test in /sanitizer_common/ to cover the case?

@sthibaul
Copy link
Contributor Author

sthibaul commented Nov 7, 2025

I added a test, but didn't find how one is supposed to run tests in compiler-rt, make help only shows GotsanRuntimeCheck OrcRTUnitTests and RTOrc.test.x86_64 which don't seem to be doing anything useful...

It allows to reserve some NULL entries at the beginning of g.gl_pathv, in
addition to the gl.gl_pathc results.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants