summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2016-12-27 22:14:03 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2016-12-27 22:14:03 +0000
commita889b3d577e7ae8df44e2f76376f08e4d54f936d (patch)
treebc4da92a66b4754d7fe25042416f4a2efa98bd36
parente03831887512c6391c1e0fbb26cebec2c8d1d07f (diff)
[asan] Fix handling of %m in printf interceptor.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@290632 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/sanitizer_common/sanitizer_common_interceptors_format.inc7
-rw-r--r--lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc4
-rw-r--r--test/asan/TestCases/printf-m.c14
3 files changed, 21 insertions, 4 deletions
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors_format.inc b/lib/sanitizer_common/sanitizer_common_interceptors_format.inc
index 92318cda3..12563499c 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors_format.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors_format.inc
@@ -435,10 +435,6 @@ static const char *printf_parse_next(const char *p, PrintfDirective *dir) {
}
static int printf_get_value_size(PrintfDirective *dir) {
- if (dir->convSpecifier == 'm') {
- return sizeof(char *);
- }
-
if (char_is_one_of(dir->convSpecifier, "cCsS")) {
unsigned charSize =
format_get_char_size(dir->convSpecifier, dir->lengthModifier);
@@ -519,6 +515,9 @@ static void printf_common(void *ctx, const char *format, va_list aq) {
// Dynamic precision
SKIP_SCALAR_ARG(&aq, 'd', sizeof(int));
}
+ // %m does not require an argument: strlen(errno).
+ if (dir.convSpecifier == 'm')
+ continue;
int size = printf_get_value_size(&dir);
if (size == FSS_INVALID) {
Report("WARNING: unexpected format specifier in printf "
diff --git a/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc b/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc
index 13918aff1..2f0494f82 100644
--- a/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc
@@ -256,4 +256,8 @@ TEST(SanitizerCommonInterceptors, Printf) {
// Checks for wide-character strings are not implemented yet.
testPrintf("%ls", 1, 0);
+
+ testPrintf("%m", 0);
+ testPrintf("%m%s", 1, test_buf_size);
+ testPrintf("%s%m%s", 2, test_buf_size, test_buf_size);
}
diff --git a/test/asan/TestCases/printf-m.c b/test/asan/TestCases/printf-m.c
new file mode 100644
index 000000000..1e5ebd92e
--- /dev/null
+++ b/test/asan/TestCases/printf-m.c
@@ -0,0 +1,14 @@
+// RUN: %clang_asan -O2 %s -o %t && %run %t
+
+// FIXME: printf is not intercepted on Windows yet.
+// XFAIL: win32
+
+#include <stdio.h>
+
+int main() {
+ char s[5] = {'w', 'o', 'r', 'l', 'd'};
+ // Test that %m does not consume an argument. If it does, %s would apply to
+ // the 5-character buffer, resulting in a stack-buffer-overflow report.
+ printf("%m %s, %.5s\n", "hello", s);
+ return 0;
+}