1*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
2*67e74705SXin Li // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
3*67e74705SXin Li // XFAIL: *
4*67e74705SXin Li
5*67e74705SXin Li // This file is for tests that may eventually go into string.c, or may be
6*67e74705SXin Li // deleted outright. At one point these tests passed, but only because we
7*67e74705SXin Li // weren't correctly modelling the behavior of the relevant string functions.
8*67e74705SXin Li // The tests aren't incorrect, but require the analyzer to be smarter about
9*67e74705SXin Li // conjured values than it currently is.
10*67e74705SXin Li
11*67e74705SXin Li //===----------------------------------------------------------------------===
12*67e74705SXin Li // Declarations
13*67e74705SXin Li //===----------------------------------------------------------------------===
14*67e74705SXin Li
15*67e74705SXin Li // Some functions are so similar to each other that they follow the same code
16*67e74705SXin Li // path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is
17*67e74705SXin Li // defined, make sure to use the variants instead to make sure they are still
18*67e74705SXin Li // checked by the analyzer.
19*67e74705SXin Li
20*67e74705SXin Li // Some functions are implemented as builtins. These should be #defined as
21*67e74705SXin Li // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
22*67e74705SXin Li
23*67e74705SXin Li // Functions that have variants and are also available as builtins should be
24*67e74705SXin Li // declared carefully! See memcpy() for an example.
25*67e74705SXin Li
26*67e74705SXin Li #ifdef USE_BUILTINS
27*67e74705SXin Li # define BUILTIN(f) __builtin_ ## f
28*67e74705SXin Li #else /* USE_BUILTINS */
29*67e74705SXin Li # define BUILTIN(f) f
30*67e74705SXin Li #endif /* USE_BUILTINS */
31*67e74705SXin Li
32*67e74705SXin Li #define NULL 0
33*67e74705SXin Li typedef typeof(sizeof(int)) size_t;
34*67e74705SXin Li
35*67e74705SXin Li void clang_analyzer_eval(int);
36*67e74705SXin Li
37*67e74705SXin Li //===----------------------------------------------------------------------===
38*67e74705SXin Li // strnlen()
39*67e74705SXin Li //===----------------------------------------------------------------------===
40*67e74705SXin Li
41*67e74705SXin Li #define strnlen BUILTIN(strnlen)
42*67e74705SXin Li size_t strnlen(const char *s, size_t maxlen);
43*67e74705SXin Li
strnlen_liveness(const char * x)44*67e74705SXin Li void strnlen_liveness(const char *x) {
45*67e74705SXin Li if (strnlen(x, 10) < 5)
46*67e74705SXin Li return;
47*67e74705SXin Li clang_analyzer_eval(strnlen(x, 10) < 5); // expected-warning{{FALSE}}
48*67e74705SXin Li }
49*67e74705SXin Li
strnlen_subregion()50*67e74705SXin Li void strnlen_subregion() {
51*67e74705SXin Li struct two_stringsn { char a[2], b[2]; };
52*67e74705SXin Li extern void use_two_stringsn(struct two_stringsn *);
53*67e74705SXin Li
54*67e74705SXin Li struct two_stringsn z;
55*67e74705SXin Li use_two_stringsn(&z);
56*67e74705SXin Li
57*67e74705SXin Li size_t a = strnlen(z.a, 10);
58*67e74705SXin Li z.b[0] = 5;
59*67e74705SXin Li size_t b = strnlen(z.a, 10);
60*67e74705SXin Li if (a == 0)
61*67e74705SXin Li clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
62*67e74705SXin Li
63*67e74705SXin Li use_two_stringsn(&z);
64*67e74705SXin Li
65*67e74705SXin Li size_t c = strnlen(z.a, 10);
66*67e74705SXin Li if (a == 0)
67*67e74705SXin Li clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
68*67e74705SXin Li }
69*67e74705SXin Li
70*67e74705SXin Li extern void use_stringn(char *);
strnlen_argument(char * x)71*67e74705SXin Li void strnlen_argument(char *x) {
72*67e74705SXin Li size_t a = strnlen(x, 10);
73*67e74705SXin Li size_t b = strnlen(x, 10);
74*67e74705SXin Li if (a == 0)
75*67e74705SXin Li clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
76*67e74705SXin Li
77*67e74705SXin Li use_stringn(x);
78*67e74705SXin Li
79*67e74705SXin Li size_t c = strnlen(x, 10);
80*67e74705SXin Li if (a == 0)
81*67e74705SXin Li clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
82*67e74705SXin Li }
83*67e74705SXin Li
84*67e74705SXin Li extern char global_strn[];
strnlen_global()85*67e74705SXin Li void strnlen_global() {
86*67e74705SXin Li size_t a = strnlen(global_strn, 10);
87*67e74705SXin Li size_t b = strnlen(global_strn, 10);
88*67e74705SXin Li if (a == 0)
89*67e74705SXin Li clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
90*67e74705SXin Li
91*67e74705SXin Li // Call a function with unknown effects, which should invalidate globals.
92*67e74705SXin Li use_stringn(0);
93*67e74705SXin Li
94*67e74705SXin Li size_t c = strnlen(global_strn, 10);
95*67e74705SXin Li if (a == 0)
96*67e74705SXin Li clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
97*67e74705SXin Li }
98*67e74705SXin Li
strnlen_indirect(char * x)99*67e74705SXin Li void strnlen_indirect(char *x) {
100*67e74705SXin Li size_t a = strnlen(x, 10);
101*67e74705SXin Li char *p = x;
102*67e74705SXin Li char **p2 = &p;
103*67e74705SXin Li size_t b = strnlen(x, 10);
104*67e74705SXin Li if (a == 0)
105*67e74705SXin Li clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
106*67e74705SXin Li
107*67e74705SXin Li extern void use_stringn_ptr(char*const*);
108*67e74705SXin Li use_stringn_ptr(p2);
109*67e74705SXin Li
110*67e74705SXin Li size_t c = strnlen(x, 10);
111*67e74705SXin Li if (a == 0)
112*67e74705SXin Li clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
113*67e74705SXin Li }
114