[compiler-rt] r199735 - [Sanitizer] Update file names now that we intercept both scanf and printf
Alexey Samsonov
samsonov at google.com
Tue Jan 21 05:01:20 PST 2014
Author: samsonov
Date: Tue Jan 21 07:01:20 2014
New Revision: 199735
URL: http://llvm.org/viewvc/llvm-project?rev=199735&view=rev
Log:
[Sanitizer] Update file names now that we intercept both scanf and printf
Added:
compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_format.inc
- copied, changed from r199730, compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc
compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc
- copied, changed from r199730, compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc
Removed:
compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc
compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc
Modified:
compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt
Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=199735&r1=199734&r2=199735&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Tue Jan 21 07:01:20 2014
@@ -46,7 +46,7 @@ set(SANITIZER_HEADERS
sanitizer_common.h
sanitizer_common_interceptors.inc
sanitizer_common_interceptors_ioctl.inc
- sanitizer_common_interceptors_scanf.inc
+ sanitizer_common_interceptors_format.inc
sanitizer_common_syscalls.inc
sanitizer_flags.h
sanitizer_internal_defs.h
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=199735&r1=199734&r2=199735&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Tue Jan 21 07:01:20 2014
@@ -570,7 +570,7 @@ INTERCEPTOR(char *, strptime, char *s, c
#endif
#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF
-#include "sanitizer_common_interceptors_scanf.inc"
+#include "sanitizer_common_interceptors_format.inc"
#define FORMAT_INTERCEPTOR_IMPL(name, vname, ...) \
{ \
Copied: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_format.inc (from r199730, compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc)
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_format.inc?p2=compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_format.inc&p1=compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc&r1=199730&r2=199735&rev=199735&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_format.inc Tue Jan 21 07:01:20 2014
@@ -1,4 +1,4 @@
-//===-- sanitizer_common_interceptors_scanf.inc -----------------*- C++ -*-===//
+//===-- sanitizer_common_interceptors_format.inc ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
Removed: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc?rev=199734&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc (removed)
@@ -1,539 +0,0 @@
-//===-- sanitizer_common_interceptors_scanf.inc -----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Scanf/printf implementation for use in *Sanitizer interceptors.
-// Follows http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html
-// and http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
-// with a few common GNU extensions.
-//
-//===----------------------------------------------------------------------===//
-#include <stdarg.h>
-
-static const char *parse_number(const char *p, int *out) {
- *out = internal_atoll(p);
- while (*p >= '0' && *p <= '9')
- ++p;
- return p;
-}
-
-static const char *maybe_parse_number(const char *p, int *out) {
- if (*p >= '0' && *p <= '9')
- p = parse_number(p, out);
- return p;
-}
-
-static const char *maybe_parse_number_or_star(const char *p, int *out,
- bool *star) {
- if (*p == '*') {
- *star = true;
- ++p;
- } else {
- *star = false;
- p = maybe_parse_number(p, out);
- }
- return p;
-}
-
-static const char *maybe_parse_param_index(const char *p, int *out) {
- // n$
- if (*p >= '0' && *p <= '9') {
- int number;
- const char *q = parse_number(p, &number);
- CHECK(q);
- if (*q == '$') {
- *out = number;
- p = q + 1;
- }
- }
-
- // Otherwise, do not change p. This will be re-parsed later as the field
- // width.
- return p;
-}
-
-static bool char_is_one_of(char c, const char *s) {
- return !!internal_strchr(s, c);
-}
-
-static const char *maybe_parse_length_modifier(const char *p, char ll[2]) {
- if (char_is_one_of(*p, "jztLq")) {
- ll[0] = *p;
- ++p;
- } else if (*p == 'h') {
- ll[0] = 'h';
- ++p;
- if (*p == 'h') {
- ll[1] = 'h';
- ++p;
- }
- } else if (*p == 'l') {
- ll[0] = 'l';
- ++p;
- if (*p == 'l') {
- ll[1] = 'l';
- ++p;
- }
- }
- return p;
-}
-
-// Returns true if the character is an integer conversion specifier.
-static bool format_is_integer_conv(char c) {
- return char_is_one_of(c, "diouxXn");
-}
-
-// Returns true if the character is an floating point conversion specifier.
-static bool format_is_float_conv(char c) {
- return char_is_one_of(c, "aAeEfFgG");
-}
-
-// Returns string output character size for string-like conversions,
-// or 0 if the conversion is invalid.
-static int format_get_char_size(char convSpecifier,
- const char lengthModifier[2]) {
- if (char_is_one_of(convSpecifier, "CS")) {
- // wchar_t
- return 0;
- }
-
- if (char_is_one_of(convSpecifier, "cs[")) {
- if (lengthModifier[0] == 'l')
- // wchar_t
- return 0;
- else if (lengthModifier[0] == 0)
- return sizeof(char);
- else
- return 0;
- }
-
- return 0;
-}
-
-enum FormatStoreSize {
- // Store size not known in advance; can be calculated as strlen() of the
- // destination buffer.
- FSS_STRLEN = -1,
- // Invalid conversion specifier.
- FSS_INVALID = 0
-};
-
-// Returns the memory size of a format directive (if >0), or a value of
-// FormatStoreSize.
-static int format_get_value_size(char convSpecifier,
- const char lengthModifier[2], int fieldWidth,
- bool promote_float) {
- if (format_is_integer_conv(convSpecifier)) {
- switch (lengthModifier[0]) {
- case 'h':
- return lengthModifier[1] == 'h' ? sizeof(char) : sizeof(short);
- case 'l':
- return lengthModifier[1] == 'l' ? sizeof(long long) : sizeof(long);
- case 'L':
- return sizeof(long long);
- case 'j':
- return sizeof(INTMAX_T);
- case 'z':
- return sizeof(SIZE_T);
- case 't':
- return sizeof(PTRDIFF_T);
- case 0:
- return sizeof(int);
- default:
- return FSS_INVALID;
- }
- }
-
- if (format_is_float_conv(convSpecifier)) {
- switch (lengthModifier[0]) {
- case 'L':
- case 'q':
- return sizeof(long double);
- case 'l':
- return lengthModifier[1] == 'l' ? sizeof(long double)
- : sizeof(double);
- case 0:
- // Printf promotes floats to doubles but scanf does not
- return promote_float ? sizeof(double) : sizeof(float);
- default:
- return FSS_INVALID;
- }
- }
-
- if (char_is_one_of(convSpecifier, "cC")) {
- unsigned charSize = format_get_char_size(convSpecifier, lengthModifier);
- if (charSize == 0)
- return FSS_INVALID;
- if (fieldWidth == 0)
- return charSize;
- return fieldWidth * charSize;
- }
-
- if (convSpecifier == 'p') {
- if (lengthModifier[0] != 0)
- return FSS_INVALID;
- return sizeof(void *);
- }
-
- return FSS_INVALID;
-}
-
-struct ScanfDirective {
- int argIdx; // argument index, or -1 if not specified ("%n$")
- int fieldWidth;
- const char *begin;
- const char *end;
- bool suppressed; // suppress assignment ("*")
- bool allocate; // allocate space ("m")
- char lengthModifier[2];
- char convSpecifier;
- bool maybeGnuMalloc;
-};
-
-// Parse scanf format string. If a valid directive in encountered, it is
-// returned in dir. This function returns the pointer to the first
-// unprocessed character, or 0 in case of error.
-// In case of the end-of-string, a pointer to the closing \0 is returned.
-static const char *scanf_parse_next(const char *p, bool allowGnuMalloc,
- ScanfDirective *dir) {
- internal_memset(dir, 0, sizeof(*dir));
- dir->argIdx = -1;
-
- while (*p) {
- if (*p != '%') {
- ++p;
- continue;
- }
- dir->begin = p;
- ++p;
- // %%
- if (*p == '%') {
- ++p;
- continue;
- }
- if (*p == '\0') {
- return 0;
- }
- // %n$
- p = maybe_parse_param_index(p, &dir->argIdx);
- CHECK(p);
- // *
- if (*p == '*') {
- dir->suppressed = true;
- ++p;
- }
- // Field width
- if (*p >= '0' && *p <= '9') {
- p = parse_number(p, &dir->fieldWidth);
- CHECK(p);
- if (dir->fieldWidth <= 0) // Width if at all must be non-zero
- return 0;
- }
- // m
- if (*p == 'm') {
- dir->allocate = true;
- ++p;
- }
- // Length modifier.
- p = maybe_parse_length_modifier(p, dir->lengthModifier);
- // Conversion specifier.
- dir->convSpecifier = *p++;
- // Consume %[...] expression.
- if (dir->convSpecifier == '[') {
- if (*p == '^')
- ++p;
- if (*p == ']')
- ++p;
- while (*p && *p != ']')
- ++p;
- if (*p == 0)
- return 0; // unexpected end of string
- // Consume the closing ']'.
- ++p;
- }
- // This is unfortunately ambiguous between old GNU extension
- // of %as, %aS and %a[...] and newer POSIX %a followed by
- // letters s, S or [.
- if (allowGnuMalloc && dir->convSpecifier == 'a' &&
- !dir->lengthModifier[0]) {
- if (*p == 's' || *p == 'S') {
- dir->maybeGnuMalloc = true;
- ++p;
- } else if (*p == '[') {
- // Watch for %a[h-j%d], if % appears in the
- // [...] range, then we need to give up, we don't know
- // if scanf will parse it as POSIX %a [h-j %d ] or
- // GNU allocation of string with range dh-j plus %.
- const char *q = p + 1;
- if (*q == '^')
- ++q;
- if (*q == ']')
- ++q;
- while (*q && *q != ']' && *q != '%')
- ++q;
- if (*q == 0 || *q == '%')
- return 0;
- p = q + 1; // Consume the closing ']'.
- dir->maybeGnuMalloc = true;
- }
- }
- dir->end = p;
- break;
- }
- return p;
-}
-
-static int scanf_get_value_size(ScanfDirective *dir) {
- if (dir->allocate) {
- if (!char_is_one_of(dir->convSpecifier, "cCsS["))
- return FSS_INVALID;
- return sizeof(char *);
- }
-
- if (dir->maybeGnuMalloc) {
- if (dir->convSpecifier != 'a' || dir->lengthModifier[0])
- return FSS_INVALID;
- // This is ambiguous, so check the smaller size of char * (if it is
- // a GNU extension of %as, %aS or %a[...]) and float (if it is
- // POSIX %a followed by s, S or [ letters).
- return sizeof(char *) < sizeof(float) ? sizeof(char *) : sizeof(float);
- }
-
- if (char_is_one_of(dir->convSpecifier, "sS[")) {
- unsigned charSize = format_get_char_size(dir->convSpecifier,
- dir->lengthModifier);
- if (charSize == 0)
- return FSS_INVALID;
- if (dir->fieldWidth == 0)
- return FSS_STRLEN;
- return (dir->fieldWidth + 1) * charSize;
- }
-
- return format_get_value_size(dir->convSpecifier, dir->lengthModifier,
- dir->fieldWidth, false);
-}
-
-// Common part of *scanf interceptors.
-// Process format string and va_list, and report all store ranges.
-// Stops when "consuming" n_inputs input items.
-static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
- const char *format, va_list aq) {
- CHECK_GT(n_inputs, 0);
- const char *p = format;
-
- COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
-
- while (*p) {
- ScanfDirective dir;
- p = scanf_parse_next(p, allowGnuMalloc, &dir);
- if (!p)
- break;
- if (dir.convSpecifier == 0) {
- // This can only happen at the end of the format string.
- CHECK_EQ(*p, 0);
- break;
- }
- // Here the directive is valid. Do what it says.
- if (dir.argIdx != -1) {
- // Unsupported.
- break;
- }
- if (dir.suppressed)
- continue;
- int size = scanf_get_value_size(&dir);
- if (size == FSS_INVALID) {
- Report("WARNING: unexpected format specifier in scanf interceptor: "
- "%.*s\n", dir.end - dir.begin, dir.begin);
- break;
- }
- void *argp = va_arg(aq, void *);
- if (dir.convSpecifier != 'n')
- --n_inputs;
- if (n_inputs < 0)
- break;
- if (size == FSS_STRLEN) {
- size = internal_strlen((const char *)argp) + 1;
- }
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
- }
-}
-
-#if SANITIZER_INTERCEPT_PRINTF
-
-struct PrintfDirective {
- int fieldWidth;
- int fieldPrecision;
- int argIdx; // width argument index, or -1 if not specified ("%*n$")
- int precisionIdx; // precision argument index, or -1 if not specified (".*n$")
- const char *begin;
- const char *end;
- bool starredWidth;
- bool starredPrecision;
- char lengthModifier[2];
- char convSpecifier;
-};
-
-// Parse printf format string. Same as scanf_parse_next.
-static const char *printf_parse_next(const char *p, PrintfDirective *dir) {
- internal_memset(dir, 0, sizeof(*dir));
- dir->argIdx = dir->precisionIdx = -1;
-
- while (*p) {
- if (*p != '%') {
- ++p;
- continue;
- }
- dir->begin = p;
- ++p;
- // %%
- if (*p == '%') {
- ++p;
- continue;
- }
- if (*p == '\0') {
- return 0;
- }
- // %n$
- p = maybe_parse_param_index(p, &dir->precisionIdx);
- CHECK(p);
- // Flags
- while (char_is_one_of(*p, "'-+ #0")) {
- ++p;
- }
- // Field width
- p = maybe_parse_number_or_star(p, &dir->fieldWidth,
- &dir->starredWidth);
- if (!p)
- return 0;
- // Precision
- if (*p == '.') {
- ++p;
- // Actual precision is optional (surprise!)
- p = maybe_parse_number_or_star(p, &dir->fieldPrecision,
- &dir->starredPrecision);
- if (!p)
- return 0;
- // m$
- if (dir->starredPrecision) {
- p = maybe_parse_param_index(p, &dir->precisionIdx);
- CHECK(p);
- }
- }
- // Length modifier.
- p = maybe_parse_length_modifier(p, dir->lengthModifier);
- // Conversion specifier.
- dir->convSpecifier = *p++;
- dir->end = p;
- break;
- }
- return p;
-}
-
-static int printf_get_value_size(PrintfDirective *dir) {
- if (dir->convSpecifier == 'm') {
- return sizeof(char *);
- }
-
- if (char_is_one_of(dir->convSpecifier, "sS")) {
- unsigned charSize = format_get_char_size(dir->convSpecifier,
- dir->lengthModifier);
- if (charSize == 0)
- return FSS_INVALID;
- return FSS_STRLEN;
- }
-
- return format_get_value_size(dir->convSpecifier, dir->lengthModifier,
- dir->fieldWidth, true);
-}
-
-#define SKIP_SCALAR_ARG(aq, convSpecifier, size) \
- do { \
- if (format_is_float_conv(convSpecifier)) { \
- switch (size) { \
- case 8: \
- va_arg(*aq, double); \
- break; \
- case 16: \
- va_arg(*aq, long double); \
- break; \
- default: \
- Report("WARNING: unexpected floating-point arg size" \
- " in printf interceptor: %d\n", size); \
- return; \
- } \
- } else { \
- switch (size) { \
- case 1: \
- case 2: \
- case 4: \
- va_arg(*aq, u32); \
- break; \
- case 8: \
- va_arg(*aq, u64); \
- break; \
- default: \
- Report("WARNING: unexpected arg size" \
- " in printf interceptor: %d\n", size); \
- return; \
- } \
- } \
- } while (0)
-
-// Common part of *printf interceptors.
-// Process format string and va_list, and report all load ranges.
-static void printf_common(void *ctx, const char *format, va_list aq) {
- COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
-
- const char *p = format;
-
- while (*p) {
- PrintfDirective dir;
- p = printf_parse_next(p, &dir);
- if (!p)
- break;
- if (dir.convSpecifier == 0) {
- // This can only happen at the end of the format string.
- CHECK_EQ(*p, 0);
- break;
- }
- // Here the directive is valid. Do what it says.
- if (dir.argIdx != -1 || dir.precisionIdx != -1) {
- // Unsupported.
- break;
- }
- if (dir.starredWidth) {
- // Dynamic width
- SKIP_SCALAR_ARG(&aq, 'd', sizeof(int));
- }
- if (dir.starredPrecision) {
- // Dynamic precision
- SKIP_SCALAR_ARG(&aq, 'd', sizeof(int));
- }
- int size = printf_get_value_size(&dir);
- if (size == FSS_INVALID) {
- Report("WARNING: unexpected format specifier in printf "
- "interceptor: %.*s\n", dir.end - dir.begin, dir.begin);
- break;
- }
- if (dir.convSpecifier == 'n') {
- void *argp = va_arg(aq, void *);
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
- continue;
- } else if (size == FSS_STRLEN) {
- if (void *argp = va_arg(aq, void *)) {
- size = internal_strlen((const char *)argp) + 1;
- COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
- }
- } else {
- // Skip non-pointer args
- SKIP_SCALAR_ARG(&aq, dir.convSpecifier, size);
- }
- }
-}
-
-#endif // SANITIZER_INTERCEPT_PRINTF
Modified: compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt?rev=199735&r1=199734&r2=199735&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt Tue Jan 21 07:01:20 2014
@@ -5,6 +5,7 @@ set(SANITIZER_UNITTESTS
sanitizer_atomic_test.cc
sanitizer_common_test.cc
sanitizer_flags_test.cc
+ sanitizer_format_interceptor_test.cc
sanitizer_ioctl_test.cc
sanitizer_libc_test.cc
sanitizer_linux_test.cc
@@ -14,7 +15,6 @@ set(SANITIZER_UNITTESTS
sanitizer_posix_test.cc
sanitizer_printf_test.cc
sanitizer_procmaps_test.cc
- sanitizer_scanf_interceptor_test.cc
sanitizer_stackdepot_test.cc
sanitizer_stacktrace_test.cc
sanitizer_stoptheworld_test.cc
Copied: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc (from r199730, compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc)
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc?p2=compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc&p1=compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc&r1=199730&r2=199735&rev=199735&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc Tue Jan 21 07:01:20 2014
@@ -1,4 +1,4 @@
-//===-- sanitizer_scanf_interceptor_test.cc -------------------------------===//
+//===-- sanitizer_format_interceptor_test.cc ------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -33,7 +33,7 @@ using namespace __sanitizer;
COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size)
#define SANITIZER_INTERCEPT_PRINTF 1
-#include "sanitizer_common/sanitizer_common_interceptors_scanf.inc"
+#include "sanitizer_common/sanitizer_common_interceptors_format.inc"
static const unsigned I = sizeof(int);
static const unsigned L = sizeof(long);
Removed: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc?rev=199734&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc (removed)
@@ -1,245 +0,0 @@
-//===-- sanitizer_scanf_interceptor_test.cc -------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Tests for *scanf interceptors implementation in sanitizer_common.
-//
-//===----------------------------------------------------------------------===//
-#include <vector>
-
-#include "interception/interception.h"
-#include "sanitizer_test_utils.h"
-#include "sanitizer_common/sanitizer_libc.h"
-#include "sanitizer_common/sanitizer_common.h"
-#include "gtest/gtest.h"
-
-using namespace __sanitizer;
-
-#define COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size) \
- do { \
- ((std::vector<unsigned> *)ctx)->push_back(size); \
- ptr = ptr; \
- } while (0)
-
-#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
- COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size)
-
-#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
- COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size)
-
-#define SANITIZER_INTERCEPT_PRINTF 1
-#include "sanitizer_common/sanitizer_common_interceptors_scanf.inc"
-
-static const unsigned I = sizeof(int);
-static const unsigned L = sizeof(long);
-static const unsigned LL = sizeof(long long);
-static const unsigned S = sizeof(short);
-static const unsigned C = sizeof(char);
-static const unsigned D = sizeof(double);
-static const unsigned LD = sizeof(long double);
-static const unsigned F = sizeof(float);
-static const unsigned P = sizeof(char *);
-
-static void verifyFormatResults(const char *format, unsigned n,
- const std::vector<unsigned> &computed_sizes,
- va_list expected_sizes) {
- // "+ 1" because of format string
- ASSERT_EQ(n + 1,
- computed_sizes.size()) << "Unexpected number of format arguments: '"
- << format << "'";
- for (unsigned i = 0; i < n; ++i)
- EXPECT_EQ(va_arg(expected_sizes, unsigned), computed_sizes[i + 1])
- << "Unexpect write size for argument " << i << ", format string '"
- << format << "'";
-}
-
-static const char test_buf[] = "Test string.";
-static const size_t test_buf_size = sizeof(test_buf);
-
-static const unsigned SCANF_ARGS_MAX = 16;
-
-static void testScanf3(void *ctx, int result, bool allowGnuMalloc,
- const char *format, ...) {
- va_list ap;
- va_start(ap, format);
- scanf_common(ctx, result, allowGnuMalloc, format, ap);
- va_end(ap);
-}
-
-static void testScanf2(const char *format, int scanf_result,
- bool allowGnuMalloc, unsigned n,
- va_list expected_sizes) {
- std::vector<unsigned> scanf_sizes;
- // 16 args should be enough.
- testScanf3((void *)&scanf_sizes, scanf_result, allowGnuMalloc, format,
- test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
- test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
- test_buf, test_buf, test_buf, test_buf);
- verifyFormatResults(format, n, scanf_sizes, expected_sizes);
-}
-
-static void testScanf(const char *format, unsigned n, ...) {
- va_list ap;
- va_start(ap, n);
- testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ true, n, ap);
- va_end(ap);
-}
-
-static void testScanfPartial(const char *format, int scanf_result, unsigned n,
- ...) {
- va_list ap;
- va_start(ap, n);
- testScanf2(format, scanf_result, /* allowGnuMalloc */ true, n, ap);
- va_end(ap);
-}
-
-static void testScanfNoGnuMalloc(const char *format, unsigned n, ...) {
- va_list ap;
- va_start(ap, n);
- testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ false, n, ap);
- va_end(ap);
-}
-
-TEST(SanitizerCommonInterceptors, Scanf) {
- testScanf("%d", 1, I);
- testScanf("%d%d%d", 3, I, I, I);
- testScanf("ab%u%dc", 2, I, I);
- testScanf("%ld", 1, L);
- testScanf("%llu", 1, LL);
- testScanf("a %hd%hhx", 2, S, C);
- testScanf("%c", 1, C);
-
- testScanf("%%", 0);
- testScanf("a%%", 0);
- testScanf("a%%b", 0);
- testScanf("a%%%%b", 0);
- testScanf("a%%b%%", 0);
- testScanf("a%%%%%%b", 0);
- testScanf("a%%%%%b", 0);
- testScanf("a%%%%%f", 1, F);
- testScanf("a%%%lxb", 1, L);
- testScanf("a%lf%%%lxb", 2, D, L);
- testScanf("%nf", 1, I);
-
- testScanf("%10s", 1, 11);
- testScanf("%10c", 1, 10);
- testScanf("%%10s", 0);
- testScanf("%*10s", 0);
- testScanf("%*d", 0);
-
- testScanf("%4d%8f%c", 3, I, F, C);
- testScanf("%s%d", 2, test_buf_size, I);
- testScanf("%[abc]", 1, test_buf_size);
- testScanf("%4[bcdef]", 1, 5);
- testScanf("%[]]", 1, test_buf_size);
- testScanf("%8[^]%d0-9-]%c", 2, 9, C);
-
- testScanf("%*[^:]%n:%d:%1[ ]%n", 4, I, I, 2, I);
-
- testScanf("%*d%u", 1, I);
-
- testScanf("%c%d", 2, C, I);
- testScanf("%A%lf", 2, F, D);
-
- testScanf("%ms %Lf", 2, P, LD);
- testScanf("s%Las", 1, LD);
- testScanf("%ar", 1, F);
-
- // In the cases with std::min below the format spec can be interpreted as
- // either floating-something, or (GNU extension) callee-allocated string.
- // Our conservative implementation reports one of the two possibilities with
- // the least store range.
- testScanf("%a[", 0);
- testScanf("%a[]", 0);
- testScanf("%a[]]", 1, std::min(F, P));
- testScanf("%a[abc]", 1, std::min(F, P));
- testScanf("%a[^abc]", 1, std::min(F, P));
- testScanf("%a[ab%c] %d", 0);
- testScanf("%a[^ab%c] %d", 0);
- testScanf("%as", 1, std::min(F, P));
- testScanf("%aS", 1, std::min(F, P));
- testScanf("%a13S", 1, std::min(F, P));
- testScanf("%alS", 1, std::min(F, P));
-
- testScanfNoGnuMalloc("s%Las", 1, LD);
- testScanfNoGnuMalloc("%ar", 1, F);
- testScanfNoGnuMalloc("%a[", 1, F);
- testScanfNoGnuMalloc("%a[]", 1, F);
- testScanfNoGnuMalloc("%a[]]", 1, F);
- testScanfNoGnuMalloc("%a[abc]", 1, F);
- testScanfNoGnuMalloc("%a[^abc]", 1, F);
- testScanfNoGnuMalloc("%a[ab%c] %d", 3, F, C, I);
- testScanfNoGnuMalloc("%a[^ab%c] %d", 3, F, C, I);
- testScanfNoGnuMalloc("%as", 1, F);
- testScanfNoGnuMalloc("%aS", 1, F);
- testScanfNoGnuMalloc("%a13S", 1, F);
- testScanfNoGnuMalloc("%alS", 1, F);
-
- testScanf("%5$d", 0);
- testScanf("%md", 0);
- testScanf("%m10s", 0);
-
- testScanfPartial("%d%d%d%d //1\n", 1, 1, I);
- testScanfPartial("%d%d%d%d //2\n", 2, 2, I, I);
- testScanfPartial("%d%d%d%d //3\n", 3, 3, I, I, I);
- testScanfPartial("%d%d%d%d //4\n", 4, 4, I, I, I, I);
-
- testScanfPartial("%d%n%n%d //1\n", 1, 3, I, I, I);
- testScanfPartial("%d%n%n%d //2\n", 2, 4, I, I, I, I);
-
- testScanfPartial("%d%n%n%d %s %s", 3, 5, I, I, I, I, test_buf_size);
- testScanfPartial("%d%n%n%d %s %s", 4, 6, I, I, I, I, test_buf_size,
- test_buf_size);
-}
-
-static void testPrintf3(void *ctx, const char *format, ...) {
- va_list ap;
- va_start(ap, format);
- printf_common(ctx, format, ap);
- va_end(ap);
-}
-
-static void testPrintf2(const char *format, unsigned n,
- va_list expected_sizes) {
- std::vector<unsigned> printf_sizes;
- // 16 args should be enough.
- testPrintf3((void *)&printf_sizes, format,
- test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
- test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
- test_buf, test_buf, test_buf, test_buf);
- verifyFormatResults(format, n, printf_sizes, expected_sizes);
-}
-
-static void testPrintf(const char *format, unsigned n, ...) {
- va_list ap;
- va_start(ap, n);
- testPrintf2(format, n, ap);
- va_end(ap);
-}
-
-TEST(SanitizerCommonInterceptors, Printf) {
- // Only test functionality which differs from scanf
-
- // Indexed arguments
- testPrintf("%5$d", 0);
- testPrintf("%.*5$d", 0);
-
- // errno
- testPrintf("%0-m", 0);
-
- // Dynamic width
- testPrintf("%*n", 1, I);
- testPrintf("%*.10n", 1, I);
-
- // Precision
- testPrintf("%10.10n", 1, I);
-
- // Dynamic precision
- testPrintf("%.*n", 1, I);
- testPrintf("%10.*n", 1, I);
-}
More information about the llvm-commits
mailing list