1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=basic -triple i386-apple-darwin9 -verify %s
2 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=basic -triple x86_64-apple-darwin9 -verify %s
3 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=range -triple i386-apple-darwin9 -verify %s
4 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=range -triple x86_64-apple-darwin9 -verify %s
5 
6 // This file runs in C++ mode so that the comparison type is 'bool', not 'int'.
7 void clang_analyzer_eval(int);
8 typedef typeof(sizeof(int)) size_t;
9 
10 // PR12206/12510 - When SimpleSValBuilder figures out that a symbol is fully
11 // constrained, it should cast the value to the result type in a binary
12 // operation...unless the binary operation is a comparison, in which case the
13 // two arguments should be the same type, but won't match the result type.
14 //
15 // This is not directly related to additive folding, but we use SValBuilder's
16 // additive folding to tickle the bug. ExprEngine will simplify fully-constrained
17 // symbols, so SValBuilder will only see them if they are (a) part of an evaluated
18 // SymExpr (e.g. with additive folding) or (b) generated by a checker (e.g.
19 // unix.cstring's strlen() modelling).
20 void PR12206(int x) {
21   size_t comparisonSize = sizeof(1 == 1);
22 
23   // Sanity check. This test is useless if size_t isn't bigger than bool.
24   clang_analyzer_eval(sizeof(size_t) > comparisonSize); // expected-warning{{TRUE}}
25 
26   // Build a SymIntExpr, dependent on x.
27   int local = x - 1;
28 
29   // Create a value that requires more bits to store than a comparison result.
30   int value = 1;
31   value <<= 8 * comparisonSize;
32   value += 1;
33 
34   // Constrain the value of x.
35   if (x != value) return;
36 
37   // Constant-folding will turn (local+1) back into the symbol for x.
38   // The point of this dance is to make SValBuilder be responsible for
39   // turning the symbol into a ConcreteInt, rather than ExprEngine.
40 
41   // Test relational operators.
42   clang_analyzer_eval((local + 1) >= 2); // expected-warning{{TRUE}}
43   clang_analyzer_eval(2 <= (local + 1)); // expected-warning{{TRUE}}
44 
45   // Test equality operators.
46   clang_analyzer_eval((local + 1) != 1); // expected-warning{{TRUE}}
47   clang_analyzer_eval(1 != (local + 1)); // expected-warning{{TRUE}}
48 }
49 
50 void PR12206_truncation(signed char x) {
51   // Build a SymIntExpr, dependent on x.
52   signed char local = x - 1;
53 
54   // Constrain the value of x.
55   if (x != 1) return;
56 
57   // Constant-folding will turn (local+1) back into the symbol for x.
58   // The point of this dance is to make SValBuilder be responsible for
59   // turning the symbol into a ConcreteInt, rather than ExprEngine.
60 
61   // Construct a value that cannot be represented by 'char',
62   // but that has the same lower bits as x.
63   signed int value = 1 + (1 << 8);
64 
65   // Test relational operators.
66   clang_analyzer_eval((local + 1) < value); // expected-warning{{TRUE}}
67   clang_analyzer_eval(value > (local + 1)); // expected-warning{{TRUE}}
68 
69   // Test equality operators.
70   clang_analyzer_eval((local + 1) != value); // expected-warning{{TRUE}}
71   clang_analyzer_eval(value != (local + 1)); // expected-warning{{TRUE}}
72 }
73 
74 // This test is insurance in case we significantly change how SymExprs are
75 // evaluated.
76 size_t strlen(const char *s);
77 void PR12206_strlen(const char *x) {
78   size_t comparisonSize = sizeof(1 == 1);
79 
80   // Sanity check. This test is useless if size_t isn't bigger than bool.
81   clang_analyzer_eval(sizeof(size_t) > comparisonSize); // expected-warning{{TRUE}}
82 
83   // Create a value that requires more bits to store than a comparison result.
84   size_t value = 1UL;
85   value <<= 8 * comparisonSize;
86   value += 1;
87 
88   // Constrain the length of x.
89   if (strlen(x) != value) return;
90 
91   // Test relational operators.
92   clang_analyzer_eval(strlen(x) >= 2); // expected-warning{{TRUE}}
93   clang_analyzer_eval(2 <= strlen(x)); // expected-warning{{TRUE}}
94 
95   // Test equality operators.
96   clang_analyzer_eval(strlen(x) != 1); // expected-warning{{TRUE}}
97   clang_analyzer_eval(1 != strlen(x)); // expected-warning{{TRUE}}
98 }
99