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