[compiler-rt] 685c94c - SIGSEGV in Sanitizer INTERCEPTOR of strstr function.

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 5 00:12:03 PST 2022


Author: Bharadwaj, Ritanya B
Date: 2022-01-05T00:11:59-08:00
New Revision: 685c94c6cbba4f2bf076b01fd3e0dcb4b1425b53

URL: https://github.com/llvm/llvm-project/commit/685c94c6cbba4f2bf076b01fd3e0dcb4b1425b53
DIFF: https://github.com/llvm/llvm-project/commit/685c94c6cbba4f2bf076b01fd3e0dcb4b1425b53.diff

LOG: SIGSEGV in Sanitizer INTERCEPTOR of strstr function.

This is a segmentation fault in INTERCEPTOR function on a special edge
case of strstr libc call. When 'Haystack'(main string to be examined) is
NULL and 'needle'(sub-string to be searched in 'Haystack') is an empty
string then it hits a SEGV while using sanitizers and as a 'string not
found' case otherwise.

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D115919

Added: 
    

Modified: 
    compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/lib/sanitizer_common/sanitizer_libc.cpp
    compiler-rt/test/sanitizer_common/TestCases/strstr.c

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index b0ab08dff1db2..4cb4d4a59f694 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -575,10 +575,12 @@ INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
 #if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR
 static inline void StrstrCheck(void *ctx, char *r, const char *s1,
                                const char *s2) {
-    uptr len1 = internal_strlen(s1);
-    uptr len2 = internal_strlen(s2);
-    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
-    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
+  uptr len2 = internal_strlen(s2);
+  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
+  if (len2 == 0 && !common_flags()->strict_string_checks)
+    return;
+  uptr len1 = internal_strlen(s1);
+  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
 }
 #endif
 

diff  --git a/compiler-rt/lib/sanitizer_common/sanitizer_libc.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_libc.cpp
index d3076f0da4891..d16e7bab69b54 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_libc.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_libc.cpp
@@ -217,8 +217,10 @@ uptr internal_strnlen(const char *s, uptr maxlen) {
 
 char *internal_strstr(const char *haystack, const char *needle) {
   // This is O(N^2), but we are not using it in hot places.
-  uptr len1 = internal_strlen(haystack);
   uptr len2 = internal_strlen(needle);
+  if (len2 == 0)
+    return const_cast<char *>(haystack);
+  uptr len1 = internal_strlen(haystack);
   if (len1 < len2) return nullptr;
   for (uptr pos = 0; pos <= len1 - len2; pos++) {
     if (internal_memcmp(haystack + pos, needle, len2) == 0)

diff  --git a/compiler-rt/test/sanitizer_common/TestCases/strstr.c b/compiler-rt/test/sanitizer_common/TestCases/strstr.c
index 2089ac7b5fcbd..d6cff1b424fd4 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/strstr.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/strstr.c
@@ -8,5 +8,9 @@ int main(int argc, char **argv) {
   char s2[] = "b";
   r = strstr(s1, s2);
   assert(r == s1 + 1);
+  char *s3 = NULL;
+  char *s4 = "";
+  char *p = strstr(s3, s4);
+  assert(p == NULL);
   return 0;
 }


        


More information about the llvm-commits mailing list