1//===-- sanitizer_scanf_interceptor_test.cc -------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Tests for *scanf interceptors implementation in sanitizer_common. 11// 12//===----------------------------------------------------------------------===// 13#include <vector> 14 15#include "interception/interception.h" 16#include "sanitizer_test_utils.h" 17#include "sanitizer_common/sanitizer_libc.h" 18#include "gtest/gtest.h" 19 20using namespace __sanitizer; 21 22#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 23 ((std::vector<unsigned> *)ctx)->push_back(size) 24 25#include "sanitizer_common/sanitizer_common_interceptors_scanf.inc" 26 27static const char scanf_buf[] = "Test string."; 28static size_t scanf_buf_size = sizeof(scanf_buf); 29static const unsigned SCANF_ARGS_MAX = 16; 30 31static void testScanf3(void *ctx, int result, bool allowGnuMalloc, 32 const char *format, ...) { 33 va_list ap; 34 va_start(ap, format); 35 scanf_common(ctx, result, allowGnuMalloc, format, ap); 36 va_end(ap); 37} 38 39static void testScanf2(const char *format, int scanf_result, 40 bool allowGnuMalloc, unsigned n, 41 va_list expected_sizes) { 42 std::vector<unsigned> scanf_sizes; 43 // 16 args should be enough. 44 testScanf3((void *)&scanf_sizes, scanf_result, allowGnuMalloc, format, 45 scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, 46 scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, 47 scanf_buf, scanf_buf, scanf_buf, scanf_buf); 48 ASSERT_EQ(n, scanf_sizes.size()) << "Unexpected number of format arguments: '" 49 << format << "'"; 50 for (unsigned i = 0; i < n; ++i) 51 EXPECT_EQ(va_arg(expected_sizes, unsigned), scanf_sizes[i]) 52 << "Unexpect write size for argument " << i << ", format string '" 53 << format << "'"; 54} 55 56static void testScanf(const char *format, unsigned n, ...) { 57 va_list ap; 58 va_start(ap, n); 59 testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ true, n, ap); 60 va_end(ap); 61} 62 63static void testScanfPartial(const char *format, int scanf_result, unsigned n, 64 ...) { 65 va_list ap; 66 va_start(ap, n); 67 testScanf2(format, scanf_result, /* allowGnuMalloc */ true, n, ap); 68 va_end(ap); 69} 70 71static void testScanfNoGnuMalloc(const char *format, unsigned n, ...) { 72 va_list ap; 73 va_start(ap, n); 74 testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ false, n, ap); 75 va_end(ap); 76} 77 78TEST(SanitizerCommonInterceptors, Scanf) { 79 const unsigned I = sizeof(int); // NOLINT 80 const unsigned L = sizeof(long); // NOLINT 81 const unsigned LL = sizeof(long long); // NOLINT 82 const unsigned S = sizeof(short); // NOLINT 83 const unsigned C = sizeof(char); // NOLINT 84 const unsigned D = sizeof(double); // NOLINT 85 const unsigned LD = sizeof(long double); // NOLINT 86 const unsigned F = sizeof(float); // NOLINT 87 const unsigned P = sizeof(char *); // NOLINT 88 89 testScanf("%d", 1, I); 90 testScanf("%d%d%d", 3, I, I, I); 91 testScanf("ab%u%dc", 2, I, I); 92 testScanf("%ld", 1, L); 93 testScanf("%llu", 1, LL); 94 testScanf("a %hd%hhx", 2, S, C); 95 testScanf("%c", 1, C); 96 97 testScanf("%%", 0); 98 testScanf("a%%", 0); 99 testScanf("a%%b", 0); 100 testScanf("a%%%%b", 0); 101 testScanf("a%%b%%", 0); 102 testScanf("a%%%%%%b", 0); 103 testScanf("a%%%%%b", 0); 104 testScanf("a%%%%%f", 1, F); 105 testScanf("a%%%lxb", 1, L); 106 testScanf("a%lf%%%lxb", 2, D, L); 107 testScanf("%nf", 1, I); 108 109 testScanf("%10s", 1, 11); 110 testScanf("%10c", 1, 10); 111 testScanf("%%10s", 0); 112 testScanf("%*10s", 0); 113 testScanf("%*d", 0); 114 115 testScanf("%4d%8f%c", 3, I, F, C); 116 testScanf("%s%d", 2, scanf_buf_size, I); 117 testScanf("%[abc]", 1, scanf_buf_size); 118 testScanf("%4[bcdef]", 1, 5); 119 testScanf("%[]]", 1, scanf_buf_size); 120 testScanf("%8[^]%d0-9-]%c", 2, 9, C); 121 122 testScanf("%*[^:]%n:%d:%1[ ]%n", 4, I, I, 2, I); 123 124 testScanf("%*d%u", 1, I); 125 126 testScanf("%c%d", 2, C, I); 127 testScanf("%A%lf", 2, F, D); 128 129 testScanf("%ms %Lf", 2, P, LD); 130 testScanf("s%Las", 1, LD); 131 testScanf("%ar", 1, F); 132 133 // In the cases with std::min below the format spec can be interpreted as 134 // either floating-something, or (GNU extension) callee-allocated string. 135 // Our conservative implementation reports one of the two possibilities with 136 // the least store range. 137 testScanf("%a[", 0); 138 testScanf("%a[]", 0); 139 testScanf("%a[]]", 1, std::min(F, P)); 140 testScanf("%a[abc]", 1, std::min(F, P)); 141 testScanf("%a[^abc]", 1, std::min(F, P)); 142 testScanf("%a[ab%c] %d", 0); 143 testScanf("%a[^ab%c] %d", 0); 144 testScanf("%as", 1, std::min(F, P)); 145 testScanf("%aS", 1, std::min(F, P)); 146 testScanf("%a13S", 1, std::min(F, P)); 147 testScanf("%alS", 1, std::min(F, P)); 148 149 testScanfNoGnuMalloc("s%Las", 1, LD); 150 testScanfNoGnuMalloc("%ar", 1, F); 151 testScanfNoGnuMalloc("%a[", 1, F); 152 testScanfNoGnuMalloc("%a[]", 1, F); 153 testScanfNoGnuMalloc("%a[]]", 1, F); 154 testScanfNoGnuMalloc("%a[abc]", 1, F); 155 testScanfNoGnuMalloc("%a[^abc]", 1, F); 156 testScanfNoGnuMalloc("%a[ab%c] %d", 3, F, C, I); 157 testScanfNoGnuMalloc("%a[^ab%c] %d", 3, F, C, I); 158 testScanfNoGnuMalloc("%as", 1, F); 159 testScanfNoGnuMalloc("%aS", 1, F); 160 testScanfNoGnuMalloc("%a13S", 1, F); 161 testScanfNoGnuMalloc("%alS", 1, F); 162 163 testScanf("%5$d", 0); 164 testScanf("%md", 0); 165 testScanf("%m10s", 0); 166 167 testScanfPartial("%d%d%d%d //1\n", 1, 1, I); 168 testScanfPartial("%d%d%d%d //2\n", 2, 2, I, I); 169 testScanfPartial("%d%d%d%d //3\n", 3, 3, I, I, I); 170 testScanfPartial("%d%d%d%d //4\n", 4, 4, I, I, I, I); 171 172 testScanfPartial("%d%n%n%d //1\n", 1, 1, I); 173 testScanfPartial("%d%n%n%d //2\n", 2, 4, I, I, I, I); 174 175 testScanfPartial("%d%n%n%d %s %s", 3, 5, I, I, I, I, scanf_buf_size); 176 testScanfPartial("%d%n%n%d %s %s", 4, 6, I, I, I, I, scanf_buf_size, 177 scanf_buf_size); 178} 179