14f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov//===-- sanitizer_scanf_interceptor_test.cc -------------------------------===//
24f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov//
34f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov//                     The LLVM Compiler Infrastructure
44f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov//
54f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov// This file is distributed under the University of Illinois Open Source
64f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov// License. See LICENSE.TXT for details.
74f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov//
84f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov//===----------------------------------------------------------------------===//
94f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov//
104f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov// Tests for *scanf interceptors implementation in sanitizer_common.
114f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov//
124f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov//===----------------------------------------------------------------------===//
13996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#include <vector>
14996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
15996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#include "interception/interception.h"
16996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#include "sanitizer_test_utils.h"
17996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#include "sanitizer_common/sanitizer_libc.h"
18996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#include "gtest/gtest.h"
19996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
20996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanovusing namespace __sanitizer;
21996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
2244be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size)                         \
23996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  ((std::vector<unsigned> *)ctx)->push_back(size)
24996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
254f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors_scanf.inc"
26996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
270527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanovstatic const char scanf_buf[] = "Test string.";
280527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanovstatic size_t scanf_buf_size = sizeof(scanf_buf);
290527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanovstatic const unsigned SCANF_ARGS_MAX = 16;
300527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov
31f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanovstatic void testScanf3(void *ctx, int result, bool allowGnuMalloc,
32f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov                       const char *format, ...) {
33996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  va_list ap;
34996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  va_start(ap, format);
35f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  scanf_common(ctx, result, allowGnuMalloc, format, ap);
36996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  va_end(ap);
37996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov}
38996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
39f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanovstatic void testScanf2(const char *format, int scanf_result,
40f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov                       bool allowGnuMalloc, unsigned n,
4144be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov                       va_list expected_sizes) {
42996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  std::vector<unsigned> scanf_sizes;
43996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  // 16 args should be enough.
44f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanf3((void *)&scanf_sizes, scanf_result, allowGnuMalloc, format,
4544be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov             scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf,
4644be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov             scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf,
47f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov             scanf_buf, scanf_buf, scanf_buf, scanf_buf);
4844be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  ASSERT_EQ(n, scanf_sizes.size()) << "Unexpected number of format arguments: '"
4944be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov                                   << format << "'";
50996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  for (unsigned i = 0; i < n; ++i)
5144be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov    EXPECT_EQ(va_arg(expected_sizes, unsigned), scanf_sizes[i])
5244be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov        << "Unexpect write size for argument " << i << ", format string '"
5344be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov        << format << "'";
540527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov}
550527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov
560527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanovstatic void testScanf(const char *format, unsigned n, ...) {
570527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  va_list ap;
580527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  va_start(ap, n);
59f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ true, n, ap);
600527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  va_end(ap);
610527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov}
620527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov
6344be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanovstatic void testScanfPartial(const char *format, int scanf_result, unsigned n,
6444be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov                             ...) {
650527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  va_list ap;
660527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  va_start(ap, n);
67f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanf2(format, scanf_result, /* allowGnuMalloc */ true,  n, ap);
68f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  va_end(ap);
69f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov}
70f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov
71f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanovstatic void testScanfNoGnuMalloc(const char *format, unsigned n, ...) {
72f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  va_list ap;
73f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  va_start(ap, n);
74f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ false, n, ap);
75996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  va_end(ap);
76996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov}
77996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
78996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy StepanovTEST(SanitizerCommonInterceptors, Scanf) {
7944be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  const unsigned I = sizeof(int);          // NOLINT
8044be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  const unsigned L = sizeof(long);         // NOLINT
8144be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  const unsigned LL = sizeof(long long);   // NOLINT
8244be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  const unsigned S = sizeof(short);        // NOLINT
8344be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  const unsigned C = sizeof(char);         // NOLINT
8444be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  const unsigned D = sizeof(double);       // NOLINT
8544be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  const unsigned LD = sizeof(long double); // NOLINT
8644be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  const unsigned F = sizeof(float);        // NOLINT
8744be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  const unsigned P = sizeof(char *);       // NOLINT
88996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
89996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("%d", 1, I);
90996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("%d%d%d", 3, I, I, I);
91996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("ab%u%dc", 2, I, I);
92996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("%ld", 1, L);
93996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("%llu", 1, LL);
94996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("a %hd%hhx", 2, S, C);
956503100c43c8951f436698b47362cdc8c2ec0a69Alexey Samsonov  testScanf("%c", 1, C);
96996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
97996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("%%", 0);
98996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("a%%", 0);
99996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("a%%b", 0);
100996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("a%%%%b", 0);
101996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("a%%b%%", 0);
102996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("a%%%%%%b", 0);
103996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("a%%%%%b", 0);
104996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("a%%%%%f", 1, F);
105996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("a%%%lxb", 1, L);
106996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("a%lf%%%lxb", 2, D, L);
107996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("%nf", 1, I);
108996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
109996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("%10s", 1, 11);
1106503100c43c8951f436698b47362cdc8c2ec0a69Alexey Samsonov  testScanf("%10c", 1, 10);
111996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("%%10s", 0);
112996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("%*10s", 0);
113996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  testScanf("%*d", 0);
1146503100c43c8951f436698b47362cdc8c2ec0a69Alexey Samsonov
1156503100c43c8951f436698b47362cdc8c2ec0a69Alexey Samsonov  testScanf("%4d%8f%c", 3, I, F, C);
116c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov  testScanf("%s%d", 2, scanf_buf_size, I);
117c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov  testScanf("%[abc]", 1, scanf_buf_size);
1183c2999e340a57a663f1b507006becfc49b368473Alexey Samsonov  testScanf("%4[bcdef]", 1, 5);
119c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov  testScanf("%[]]", 1, scanf_buf_size);
1203c2999e340a57a663f1b507006becfc49b368473Alexey Samsonov  testScanf("%8[^]%d0-9-]%c", 2, 9, C);
1213c2999e340a57a663f1b507006becfc49b368473Alexey Samsonov
1223c2999e340a57a663f1b507006becfc49b368473Alexey Samsonov  testScanf("%*[^:]%n:%d:%1[ ]%n", 4, I, I, 2, I);
123c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov
124c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov  testScanf("%*d%u", 1, I);
125c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov
1264f06d0ba90aae87a21f3a7d75db985a01b8fb6d2Evgeniy Stepanov  testScanf("%c%d", 2, C, I);
1274f06d0ba90aae87a21f3a7d75db985a01b8fb6d2Evgeniy Stepanov  testScanf("%A%lf", 2, F, D);
1284f06d0ba90aae87a21f3a7d75db985a01b8fb6d2Evgeniy Stepanov
1290e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%ms %Lf", 2, P, LD);
1300e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("s%Las", 1, LD);
1310e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%ar", 1, F);
1320e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov
1330e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  // In the cases with std::min below the format spec can be interpreted as
1340e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  // either floating-something, or (GNU extension) callee-allocated string.
1350e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  // Our conservative implementation reports one of the two possibilities with
1360e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  // the least store range.
137c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov  testScanf("%a[", 0);
1380e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%a[]", 0);
1390e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%a[]]", 1, std::min(F, P));
1400e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%a[abc]", 1, std::min(F, P));
1410e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%a[^abc]", 1, std::min(F, P));
1420e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%a[ab%c] %d", 0);
1430e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%a[^ab%c] %d", 0);
1440e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%as", 1, std::min(F, P));
1450e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%aS", 1, std::min(F, P));
1460e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%a13S", 1, std::min(F, P));
1470e43e9ea9a1d5453fe1c25a6ec3927b417a8f5b1Evgeniy Stepanov  testScanf("%alS", 1, std::min(F, P));
148c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov
149f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("s%Las", 1, LD);
150f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%ar", 1, F);
151f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%a[", 1, F);
152f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%a[]", 1, F);
153f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%a[]]", 1, F);
154f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%a[abc]", 1, F);
155f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%a[^abc]", 1, F);
156f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%a[ab%c] %d", 3, F, C, I);
157f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%a[^ab%c] %d", 3, F, C, I);
158f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%as", 1, F);
159f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%aS", 1, F);
160f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%a13S", 1, F);
161f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov  testScanfNoGnuMalloc("%alS", 1, F);
162f4a1ea7e0130273039f6c76d97e852f28e572d7aEvgeniy Stepanov
163c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov  testScanf("%5$d", 0);
164c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov  testScanf("%md", 0);
165c36c168f8f482f35f200fea57dd88a888bf062fbEvgeniy Stepanov  testScanf("%m10s", 0);
1660527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov
1670527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  testScanfPartial("%d%d%d%d //1\n", 1, 1, I);
1680527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  testScanfPartial("%d%d%d%d //2\n", 2, 2, I, I);
1690527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  testScanfPartial("%d%d%d%d //3\n", 3, 3, I, I, I);
1700527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  testScanfPartial("%d%d%d%d //4\n", 4, 4, I, I, I, I);
1710527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov
1720527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  testScanfPartial("%d%n%n%d //1\n", 1, 1, I);
1730527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  testScanfPartial("%d%n%n%d //2\n", 2, 4, I, I, I, I);
1740527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov
1750527bf2e6aa5b35da8aa57e866287ab66af67c15Evgeniy Stepanov  testScanfPartial("%d%n%n%d %s %s", 3, 5, I, I, I, I, scanf_buf_size);
17644be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov  testScanfPartial("%d%n%n%d %s %s", 4, 6, I, I, I, I, scanf_buf_size,
17744be70b186549d592c952a13aafe79bfeae89f81Evgeniy Stepanov                   scanf_buf_size);
178996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov}
179