[compiler-rt] 94b0851 - [sanitizer] use uptr to store the result of internal_strlen/internal_strnlen in printf_common
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 27 23:37:48 PDT 2023
Author: Enna1
Date: 2023-08-28T14:37:35+08:00
New Revision: 94b0851aad618397f508e56c63c6f928e4e911b9
URL: https://github.com/llvm/llvm-project/commit/94b0851aad618397f508e56c63c6f928e4e911b9
DIFF: https://github.com/llvm/llvm-project/commit/94b0851aad618397f508e56c63c6f928e4e911b9.diff
LOG: [sanitizer] use uptr to store the result of internal_strlen/internal_strnlen in printf_common
The return type of `internal_strlen()` is 'uptr', but in `printf_common()` we store the result of `internal_strlen()` into an 'int' type variable.
When the result value of `internal_strlen()` is larger than the largest possible value of 'int' type, the implicit conversion from 'uptr' to 'int' will change the result value to a negative value.
Without this change, asan reports a false positive negative-size-param in the added testcase.
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D157266
Added:
compiler-rt/test/sanitizer_common/TestCases/vsnprintf.cpp
Modified:
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc
Removed:
################################################################################
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc
index 24485900644b38..24e5dc0fb22f5e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc
@@ -547,24 +547,25 @@ static void printf_common(void *ctx, const char *format, va_list aq) {
continue;
} else if (size == FSS_STRLEN) {
if (void *argp = va_arg(aq, void *)) {
+ uptr len;
if (dir.starredPrecision) {
// FIXME: properly support starred precision for strings.
- size = 0;
+ len = 0;
} else if (dir.fieldPrecision > 0) {
// Won't read more than "precision" symbols.
- size = internal_strnlen((const char *)argp, dir.fieldPrecision);
- if (size < dir.fieldPrecision) size++;
+ len = internal_strnlen((const char *)argp, dir.fieldPrecision);
+ if (len < (uptr)dir.fieldPrecision)
+ len++;
} else {
// Whole string will be accessed.
- size = internal_strlen((const char *)argp) + 1;
+ len = internal_strlen((const char *)argp) + 1;
}
- COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, len);
}
} else if (size == FSS_WCSLEN) {
if (void *argp = va_arg(aq, void *)) {
// FIXME: Properly support wide-character strings (via wcsrtombs).
- size = 0;
- COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, 0);
}
} else {
// Skip non-pointer args
diff --git a/compiler-rt/test/sanitizer_common/TestCases/vsnprintf.cpp b/compiler-rt/test/sanitizer_common/TestCases/vsnprintf.cpp
new file mode 100644
index 00000000000000..4eb9b24770f5d3
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/vsnprintf.cpp
@@ -0,0 +1,34 @@
+// Test that the common part implementation of *printf interceptors does not
+// cause negative-size-param false positives.
+
+// RUN: %clangxx -O2 %s -o %t
+// RUN: %env_tool_opts=check_printf=1 %run %t 2>&1
+
+// FIXME: The maximum supported allocation size is too platform-specific:
+// REQUIRES: x86_64-target-arch
+
+// FIXME: printf is not intercepted on Windows yet.
+// UNSUPPORTED: target={{.*windows-msvc.*}}
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void write(char *buf, int buf_size, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(buf, buf_size, fmt, args);
+ va_end(args);
+}
+
+int main() {
+ char buffer[100];
+ const size_t kStrSize = 1UL << 31;
+ char *x = (char *)malloc(kStrSize);
+ memset(x, '=', kStrSize - 1);
+ x[kStrSize - 1] = 0;
+ write(buffer, 100, "%s\n", x);
+ free(x);
+ return 0;
+}
More information about the llvm-commits
mailing list