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