// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,unix.Malloc -verify -analyzer-constraints=basic %s // RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,unix.Malloc -verify -analyzer-constraints=range %s // These are used to trigger warnings. typedef typeof(sizeof(int)) size_t; void *malloc(size_t); void free(void *); #define NULL ((void*)0) #define UINT_MAX (~0U) #define INT_MAX (UINT_MAX & (UINT_MAX >> 1)) #define INT_MIN (-INT_MAX - 1) //--------------- // Plus/minus //--------------- void separateExpressions (int a) { int b = a + 1; --b; void *buf = malloc(1); if (a != 0 && b == 0) return; // expected-warning{{never executed}} free(buf); } void oneLongExpression (int a) { // Expression canonicalization should still allow this to work, even though // the first term is on the left. int b = 15 + a + 15 - 10 - 20; void *buf = malloc(1); if (a != 0 && b == 0) return; // expected-warning{{never executed}} free(buf); } void mixedTypes (int a) { void *buf = malloc(1); // Different additive types should not cause crashes when constant-folding. // This is part of PR7406. int b = a + 1LL; if (a != 0 && (b-1) == 0) // not crash return; // expected-warning{{never executed}} int c = a + 1U; if (a != 0 && (c-1) == 0) // not crash return; // expected-warning{{never executed}} free(buf); } //--------------- // Comparisons //--------------- // Equality and inequality only void eq_ne (unsigned a) { void *b = NULL; if (a == UINT_MAX) b = malloc(1); if (a+1 != 0) return; // no-warning if (a-1 != UINT_MAX-1) return; // no-warning free(b); } void ne_eq (unsigned a) { void *b = NULL; if (a != UINT_MAX) b = malloc(1); if (a+1 == 0) return; // no-warning if (a-1 == UINT_MAX-1) return; // no-warning free(b); } // Mixed typed inequalities (part of PR7406) // These should not crash. void mixed_eq_ne (int a) { void *b = NULL; if (a == 1) b = malloc(1); if (a+1U != 2) return; // no-warning if (a-1U != 0) return; // expected-warning{{never executed}} free(b); } void mixed_ne_eq (int a) { void *b = NULL; if (a != 1) b = malloc(1); if (a+1U == 2) return; // no-warning if (a-1U == 0) return; // expected-warning{{never executed}} free(b); } // Simple order comparisons with no adjustment void baselineGT (unsigned a) { void *b = NULL; if (a > 0) b = malloc(1); if (a == 0) return; // no-warning free(b); } void baselineGE (unsigned a) { void *b = NULL; if (a >= UINT_MAX) b = malloc(1); if (a == UINT_MAX) free(b); return; // no-warning } void baselineLT (unsigned a) { void *b = NULL; if (a < UINT_MAX) b = malloc(1); if (a == UINT_MAX) return; // no-warning free(b); } void baselineLE (unsigned a) { void *b = NULL; if (a <= 0) b = malloc(1); if (a == 0) free(b); return; // no-warning } // Adjustment gives each of these an extra solution! void adjustedGT (unsigned a) { void *b = NULL; if (a-1 > UINT_MAX-1) b = malloc(1); return; // expected-warning{{leak}} } void adjustedGE (unsigned a) { void *b = NULL; if (a-1 >= UINT_MAX-1) b = malloc(1); if (a == UINT_MAX) free(b); return; // expected-warning{{leak}} } void adjustedLT (unsigned a) { void *b = NULL; if (a+1 < 1) b = malloc(1); return; // expected-warning{{leak}} } void adjustedLE (unsigned a) { void *b = NULL; if (a+1 <= 1) b = malloc(1); if (a == 0) free(b); return; // expected-warning{{leak}} } // Tautologies void tautologyGT (unsigned a) { void *b = malloc(1); if (a > UINT_MAX) return; // no-warning free(b); } void tautologyGE (unsigned a) { void *b = malloc(1); if (a >= 0) // expected-warning{{always true}} free(b); return; // no-warning } void tautologyLT (unsigned a) { void *b = malloc(1); if (a < 0) // expected-warning{{always false}} return; // expected-warning{{never executed}} free(b); } void tautologyLE (unsigned a) { void *b = malloc(1); if (a <= UINT_MAX) free(b); return; // no-warning } // Tautologies from outside the range of the symbol void tautologyOutsideGT(unsigned char a) { void *b = malloc(1); if (a > 0x100) return; // expected-warning{{never executed}} if (a > -1) free(b); return; // no-warning } void tautologyOutsideGE(unsigned char a) { void *b = malloc(1); if (a >= 0x100) return; // expected-warning{{never executed}} if (a >= -1) free(b); return; // no-warning } void tautologyOutsideLT(unsigned char a) { void *b = malloc(1); if (a < -1) return; // expected-warning{{never executed}} if (a < 0x100) free(b); return; // no-warning } void tautologyOutsideLE (unsigned char a) { void *b = malloc(1); if (a <= -1) return; // expected-warning{{never executed}} if (a <= 0x100) free(b); return; // no-warning } void tautologyOutsideEQ(unsigned char a) { if (a == 0x100) malloc(1); // expected-warning{{never executed}} if (a == -1) malloc(1); // expected-warning{{never executed}} } void tautologyOutsideNE(unsigned char a) { void *sentinel = malloc(1); if (a != 0x100) free(sentinel); sentinel = malloc(1); if (a != -1) free(sentinel); } // Wraparound with mixed types. Note that the analyzer assumes // -fwrapv semantics. void mixedWraparoundSanityCheck(int a) { int max = INT_MAX; int min = INT_MIN; int b = a + 1; if (a == max && b != min) return; // expected-warning{{never executed}} } void mixedWraparoundGT(int a) { int max = INT_MAX; if ((a + 2) > (max + 1LL)) return; // expected-warning{{never executed}} } void mixedWraparoundGE(int a) { int max = INT_MAX; int min = INT_MIN; if ((a + 2) >= (max + 1LL)) return; // expected-warning{{never executed}} void *sentinel = malloc(1); if ((a - 2LL) >= min) free(sentinel); return; // expected-warning{{leak}} } void mixedWraparoundLT(int a) { int min = INT_MIN; if ((a - 2) < (min - 1LL)) return; // expected-warning{{never executed}} } void mixedWraparoundLE(int a) { int max = INT_MAX; int min = INT_MIN; if ((a - 2) <= (min - 1LL)) return; // expected-warning{{never executed}} void *sentinel = malloc(1); if ((a + 2LL) <= max) free(sentinel); return; // expected-warning{{leak}} } void mixedWraparoundEQ(int a) { int max = INT_MAX; if ((a + 2) == (max + 1LL)) return; // expected-warning{{never executed}} } void mixedWraparoundNE(int a) { int max = INT_MAX; void *sentinel = malloc(1); if ((a + 2) != (max + 1LL)) free(sentinel); return; // no-warning } // Mixed-signedness comparisons. void mixedSignedness(int a, unsigned b) { int sMin = INT_MIN; unsigned uMin = INT_MIN; if (a == sMin && a != uMin) return; // expected-warning{{never executed}} if (b == uMin && b != sMin) return; // expected-warning{{never executed}} } // PR12206/12510 - When SimpleSValBuilder figures out that a symbol is fully // constrained, it should cast the value to the result type in a binary // operation...unless the binary operation is a comparison, in which case the // two arguments should be the same type, but won't match the result type. // // This is easier to trigger in C++ mode, where the comparison result type is // 'bool' and is thus differently sized from int on pretty much every system. // // This is not directly related to additive folding, but we use SValBuilder's // additive folding to tickle the bug. ExprEngine will simplify fully-constrained // symbols, so SValBuilder will only see them if they are (a) part of an evaluated // SymExpr (e.g. with additive folding) or (b) generated by a checker (e.g. // unix.cstring's strlen() modelling). void PR12206(int x) { // Build a SymIntExpr, dependent on x. int local = x - 1; // Constrain the value of x. int value = 1 + (1 << (8 * sizeof(1 == 1))); // not representable by bool if (x != value) return; // Constant-folding will turn (local+1) back into the symbol for x. // The point of this dance is to make SValBuilder be responsible for // turning the symbol into a ConcreteInt, rather than ExprEngine. // Test relational operators. if ((local + 1) < 2) malloc(1); // expected-warning{{never executed}} if (2 > (local + 1)) malloc(1); // expected-warning{{never executed}} // Test equality operators. if ((local + 1) == 1) malloc(1); // expected-warning{{never executed}} if (1 == (local + 1)) malloc(1); // expected-warning{{never executed}} } void PR12206_truncation(signed char x) { // Build a SymIntExpr, dependent on x. signed char local = x - 1; // Constrain the value of x. if (x != 1) return; // Constant-folding will turn (local+1) back into the symbol for x. // The point of this dance is to make SValBuilder be responsible for // turning the symbol into a ConcreteInt, rather than ExprEngine. // Construct a value that cannot be represented by 'char', // but that has the same lower bits as x. signed int value = 1 + (1 << 8); // Test relational operators. if ((local + 1) >= value) malloc(1); // expected-warning{{never executed}} if (value <= (local + 1)) malloc(1); // expected-warning{{never executed}} // Test equality operators. if ((local + 1) == value) malloc(1); // expected-warning{{never executed}} if (value == (local + 1)) malloc(1); // expected-warning{{never executed}} } void multiplicativeSanityTest(int x) { // At one point we were ignoring the *4 completely -- the constraint manager // would see x < 8 and then declare the next part unreachable. if (x*4 < 8) return; if (x == 3) malloc(1); return; // expected-warning{{leak}} }