[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