xref: /llvm-project/clang/test/Analysis/std-c-library-functions-arg-constraints.c (revision bd03ef19beb8a3476d5cd9f744c5fba5ca287c51)
1 // Check the basic reporting/warning and the application of constraints.
2 // RUN: %clang_analyze_cc1 %s \
3 // RUN:   -analyzer-checker=core \
4 // RUN:   -analyzer-checker=apiModeling.StdCLibraryFunctions \
5 // RUN:   -analyzer-checker=alpha.apiModeling.StdCLibraryFunctionArgs \
6 // RUN:   -analyzer-checker=debug.StdCLibraryFunctionsTester \
7 // RUN:   -analyzer-checker=debug.ExprInspection \
8 // RUN:   -triple x86_64-unknown-linux-gnu \
9 // RUN:   -verify=report
10 
11 // Check the bugpath related to the reports.
12 // RUN: %clang_analyze_cc1 %s \
13 // RUN:   -analyzer-checker=core \
14 // RUN:   -analyzer-checker=apiModeling.StdCLibraryFunctions \
15 // RUN:   -analyzer-checker=alpha.apiModeling.StdCLibraryFunctionArgs \
16 // RUN:   -analyzer-checker=debug.StdCLibraryFunctionsTester \
17 // RUN:   -analyzer-checker=debug.ExprInspection \
18 // RUN:   -triple x86_64-unknown-linux-gnu \
19 // RUN:   -analyzer-output=text \
20 // RUN:   -verify=bugpath
21 
22 void clang_analyzer_eval(int);
23 
24 int glob;
25 
26 #define EOF -1
27 
28 int isalnum(int);
29 
30 void test_alnum_concrete(int v) {
31   int ret = isalnum(256); // \
32   // report-warning{{Function argument constraint is not satisfied}} \
33   // bugpath-warning{{Function argument constraint is not satisfied}} \
34   // bugpath-note{{Function argument constraint is not satisfied}}
35   (void)ret;
36 }
37 
38 void test_alnum_symbolic(int x) {
39   int ret = isalnum(x);
40   (void)ret;
41 
42   clang_analyzer_eval(EOF <= x && x <= 255); // \
43   // report-warning{{TRUE}} \
44   // bugpath-warning{{TRUE}} \
45   // bugpath-note{{TRUE}} \
46   // bugpath-note{{Left side of '&&' is true}} \
47   // bugpath-note{{'x' is <= 255}}
48 
49 }
50 
51 void test_alnum_symbolic2(int x) {
52   if (x > 255) { // \
53     // bugpath-note{{Assuming 'x' is > 255}} \
54     // bugpath-note{{Taking true branch}}
55 
56     int ret = isalnum(x); // \
57     // report-warning{{Function argument constraint is not satisfied}} \
58     // bugpath-warning{{Function argument constraint is not satisfied}} \
59     // bugpath-note{{Function argument constraint is not satisfied}}
60 
61     (void)ret;
62   }
63 }
64 
65 typedef struct FILE FILE;
66 typedef typeof(sizeof(int)) size_t;
67 size_t fread(void *restrict, size_t, size_t, FILE *);
68 void test_notnull_concrete(FILE *fp) {
69   fread(0, sizeof(int), 10, fp); // \
70   // report-warning{{Function argument constraint is not satisfied}} \
71   // bugpath-warning{{Function argument constraint is not satisfied}} \
72   // bugpath-note{{Function argument constraint is not satisfied}}
73 }
74 void test_notnull_symbolic(FILE *fp, int *buf) {
75   fread(buf, sizeof(int), 10, fp);
76   clang_analyzer_eval(buf != 0); // \
77   // report-warning{{TRUE}} \
78   // bugpath-warning{{TRUE}} \
79   // bugpath-note{{TRUE}} \
80   // bugpath-note{{'buf' is not equal to null}}
81 }
82 void test_notnull_symbolic2(FILE *fp, int *buf) {
83   if (!buf) // bugpath-note{{Assuming 'buf' is null}} \
84             // bugpath-note{{Taking true branch}}
85     fread(buf, sizeof(int), 10, fp); // \
86     // report-warning{{Function argument constraint is not satisfied}} \
87     // bugpath-warning{{Function argument constraint is not satisfied}} \
88     // bugpath-note{{Function argument constraint is not satisfied}}
89 }
90 
91 int __two_constrained_args(int, int);
92 void test_constraints_on_multiple_args(int x, int y) {
93   // State split should not happen here. I.e. x == 1 should not be evaluated
94   // FALSE.
95   __two_constrained_args(x, y);
96   clang_analyzer_eval(x == 1); // \
97   // report-warning{{TRUE}} \
98   // bugpath-warning{{TRUE}} \
99   // bugpath-note{{TRUE}}
100   clang_analyzer_eval(y == 1); // \
101   // report-warning{{TRUE}} \
102   // bugpath-warning{{TRUE}} \
103   // bugpath-note{{TRUE}}
104 }
105 
106 int __arg_constrained_twice(int);
107 void test_multiple_constraints_on_same_arg(int x) {
108   __arg_constrained_twice(x);
109   // Check that both constraints are applied and only one branch is there.
110   clang_analyzer_eval(x < 1 || x > 2); // \
111   // report-warning{{TRUE}} \
112   // bugpath-warning{{TRUE}} \
113   // bugpath-note{{TRUE}} \
114   // bugpath-note{{Assuming 'x' is < 1}} \
115   // bugpath-note{{Left side of '||' is true}}
116 }
117 
118 int __variadic(void *stream, const char *format, ...);
119 void test_arg_constraint_on_variadic_fun() {
120   __variadic(0, "%d%d", 1, 2); // \
121   // report-warning{{Function argument constraint is not satisfied}} \
122   // bugpath-warning{{Function argument constraint is not satisfied}} \
123   // bugpath-note{{Function argument constraint is not satisfied}}
124 }
125 
126 int __buf_size_arg_constraint(const void *, size_t);
127 void test_buf_size_concrete() {
128   char buf[3];                       // bugpath-note{{'buf' initialized here}}
129   __buf_size_arg_constraint(buf, 4); // \
130   // report-warning{{Function argument constraint is not satisfied}} \
131   // bugpath-warning{{Function argument constraint is not satisfied}} \
132   // bugpath-note{{Function argument constraint is not satisfied}}
133 }
134 void test_buf_size_symbolic(int s) {
135   char buf[3];
136   __buf_size_arg_constraint(buf, s);
137   clang_analyzer_eval(s <= 3); // \
138   // report-warning{{TRUE}} \
139   // bugpath-warning{{TRUE}} \
140   // bugpath-note{{TRUE}} \
141   // bugpath-note{{'s' is <= 3}}
142 }
143 void test_buf_size_symbolic_and_offset(int s) {
144   char buf[3];
145   __buf_size_arg_constraint(buf + 1, s);
146   clang_analyzer_eval(s <= 2); // \
147   // report-warning{{TRUE}} \
148   // bugpath-warning{{TRUE}} \
149   // bugpath-note{{TRUE}} \
150   // bugpath-note{{'s' is <= 2}}
151 }
152