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