[gcc r11-7555] libsanitizer: cherry-pick ad294e572bc5c16f9dc420cc994322de6ca3fbfb

Martin Liska marxin@gcc.gnu.org
Mon Mar 8 14:55:39 GMT 2021


https://gcc.gnu.org/g:81fee438512460f1be50d91ee5de452f8fe5cc18

commit r11-7555-g81fee438512460f1be50d91ee5de452f8fe5cc18
Author: Martin Liska <mliska@suse.cz>
Date:   Mon Mar 8 15:52:03 2021 +0100

    libsanitizer: cherry-pick ad294e572bc5c16f9dc420cc994322de6ca3fbfb
    
    libsanitizer/ChangeLog:
    
            PR sanitizer/98920
            * asan/asan_interceptors.cpp (COMMON_INTERCEPT_FUNCTION_VER):
            Cherry pick.
            (COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK): Likewise.
            * asan/asan_interceptors.h (ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK): Likewise.
            * sanitizer_common/sanitizer_common_interceptors.inc
            (COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN): Likewise.
            (INIT_REGEX): Likewise.
            * tsan/tsan_interceptors_posix.cpp (COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK):
            Likewise.
    
    gcc/testsuite/ChangeLog:
    
            PR sanitizer/98920
            * c-c++-common/asan/pr98920.c: New test.

Diff:
---
 gcc/testsuite/c-c++-common/asan/pr98920.c          | 24 ++++++++++++++++++++++
 libsanitizer/asan/asan_interceptors.cpp            |  5 ++++-
 libsanitizer/asan/asan_interceptors.h              |  7 +++++++
 .../sanitizer_common_interceptors.inc              | 19 ++++++++++++++++-
 libsanitizer/tsan/tsan_interceptors_posix.cpp      |  2 ++
 5 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/c-c++-common/asan/pr98920.c b/gcc/testsuite/c-c++-common/asan/pr98920.c
new file mode 100644
index 00000000000..881d3d4901e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr98920.c
@@ -0,0 +1,24 @@
+/* PR sanitizer/98920 */
+/* { dg-do run } */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <regex.h>
+
+int main(void)
+{
+    regex_t r;
+    const char s[] = "ban\0ana";
+    regmatch_t pmatch[10];
+    pmatch[0].rm_so = 0;
+    pmatch[0].rm_eo = sizeof(s);
+    if (regcomp(&r, "ana", 0))
+        return 2;
+    if (regexec(&r, s, sizeof(pmatch)/sizeof(pmatch[0]), pmatch, REG_STARTEND)) {
+        fprintf(stderr, "failed to match\n");
+        regfree(&r);
+        return 3;
+    }
+    regfree(&r);
+    return 0;
+}
diff --git a/libsanitizer/asan/asan_interceptors.cpp b/libsanitizer/asan/asan_interceptors.cpp
index b19cf25c7cd..4e68b3b0b47 100644
--- a/libsanitizer/asan/asan_interceptors.cpp
+++ b/libsanitizer/asan/asan_interceptors.cpp
@@ -90,8 +90,10 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
   (void) ctx;                                                                  \
 
 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
-#define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
+#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
   ASAN_INTERCEPT_FUNC_VER(name, ver)
+#define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
+  ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
   ASAN_WRITE_RANGE(ctx, ptr, size)
 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
@@ -687,6 +689,7 @@ void InitializeAsanInterceptors() {
 
   // Intercept threading-related functions
 #if ASAN_INTERCEPT_PTHREAD_CREATE
+// TODO: this should probably have an unversioned fallback for newer arches?
 #if defined(ASAN_PTHREAD_CREATE_VERSION)
   ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
 #else
diff --git a/libsanitizer/asan/asan_interceptors.h b/libsanitizer/asan/asan_interceptors.h
index 43cb4e3bb4f..56dc34b7d93 100644
--- a/libsanitizer/asan/asan_interceptors.h
+++ b/libsanitizer/asan/asan_interceptors.h
@@ -150,6 +150,13 @@ DECLARE_REAL(char*, strstr, const char *s1, const char *s2)
       VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", #name, \
               #ver);                                                        \
   } while (0)
+#define ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)              \
+  do {                                                                       \
+    if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name))     \
+      VReport(1, "AddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \
+              #name, #ver, #name);                                           \
+  } while (0)
+
 #else
 // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
 #define ASAN_INTERCEPT_FUNC(name)
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
index 729eead43c0..2f2787e283a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
@@ -239,6 +239,23 @@ extern const short *_tolower_tab_;
     COMMON_INTERCEPT_FUNCTION(fn)
 #endif
 
+#ifdef __GLIBC__
+// If we could not find the versioned symbol, fall back to an unversioned
+// lookup. This is needed to work around a GLibc bug that causes dlsym
+// with RTLD_NEXT to return the oldest versioned symbol.
+// See https://sourceware.org/bugzilla/show_bug.cgi?id=14932.
+// For certain symbols (e.g. regexec) we have to perform a versioned lookup,
+// but that versioned symbol will only exist for architectures where the
+// oldest Glibc version pre-dates support for that architecture.
+// For example, regexec@GLIBC_2.3.4 exists on x86_64, but not RISC-V.
+// See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98920.
+#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
+  COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(fn, ver)
+#else
+#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
+  COMMON_INTERCEPT_FUNCTION(fn)
+#endif
+
 #ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
   {                                                       \
@@ -7772,7 +7789,7 @@ INTERCEPTOR(void, regfree, const void *preg) {
 }
 #define INIT_REGEX                                                             \
   COMMON_INTERCEPT_FUNCTION(regcomp);                                          \
-  COMMON_INTERCEPT_FUNCTION(regexec);                                          \
+  COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(regexec, "GLIBC_2.3.4");             \
   COMMON_INTERCEPT_FUNCTION(regerror);                                         \
   COMMON_INTERCEPT_FUNCTION(regfree);
 #else
diff --git a/libsanitizer/tsan/tsan_interceptors_posix.cpp b/libsanitizer/tsan/tsan_interceptors_posix.cpp
index 20c2747aaea..aa04d8dfb67 100644
--- a/libsanitizer/tsan/tsan_interceptors_posix.cpp
+++ b/libsanitizer/tsan/tsan_interceptors_posix.cpp
@@ -2227,6 +2227,8 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
 #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
   INTERCEPT_FUNCTION_VER(name, ver)
+#define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
+  (INTERCEPT_FUNCTION_VER(name, ver) || INTERCEPT_FUNCTION(name))
 
 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size)                    \
   MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr,                 \


More information about the Gcc-cvs mailing list