diff --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp --- a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -222,6 +222,12 @@ std::tie(RootNonLoc, ConstantFoldedRHS) = simplify(SVB, RawOffset.getByteOffset(), Zero); + // No unsigned symbolic value can be less then a negative constant. + if (const auto SymbolicRoot = RootNonLoc.getAs()) + if (SymbolicRoot->getSymbol()->getType()->isUnsignedIntegerType() && + ConstantFoldedRHS.castAs().getValue().isNegative()) + return State; + NonLoc LowerBoundCheck = SVB.evalBinOpNN(State, BO_LT, RootNonLoc.castAs(), ConstantFoldedRHS.castAs(), diff --git a/clang/test/Analysis/out-of-bounds-false-positive.c b/clang/test/Analysis/out-of-bounds-false-positive.c --- a/clang/test/Analysis/out-of-bounds-false-positive.c +++ b/clang/test/Analysis/out-of-bounds-false-positive.c @@ -8,12 +8,11 @@ const char a[] = "abcd"; // extent: 5 bytes void symbolic_size_t_and_int0(size_t len) { - // FIXME: Should not warn for this. - (void)a[len + 1]; // expected-warning {{Out of bound memory access}} + (void)a[len + 1]; // no-warning // We infered that the 'len' must be in a specific range to make the previous indexing valid. // len: [0,3] - clang_analyzer_eval(len <= 3); // expected - warning {{TRUE}} - clang_analyzer_eval(len <= 2); // expected - warning {{UNKNOWN}} + clang_analyzer_eval(len <= 3); // expected-warning {{TRUE}} + clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} } void symbolic_size_t_and_int1(size_t len) {