================ @@ -379,6 +386,111 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S, C.addTransition(State, this); } +void DereferenceChecker::checkPreStmt(const BinaryOperator *Op, + CheckerContext &C) const { + if (!Op->isAdditiveOp()) + return; + const Expr *E1 = Op->getLHS(); + const Expr *E2 = Op->getRHS(); + QualType T1 = E1->getType().getCanonicalType(); + QualType T2 = E2->getType().getCanonicalType(); + if (T1->isIntegerType() && T2->isIntegerType()) + return; + if (!T1->isPointerType() && !T1->isIntegerType() && !T2->isPointerType() && + !T2->isIntegerType()) + return; + + ProgramStateRef State = C.getState(); + SVal V1 = State->getSVal(E1, C.getLocationContext()); + SVal V2 = State->getSVal(E2, C.getLocationContext()); + if (V1.isUndef() || V2.isUndef()) + return; + + ConditionTruthVal V1IsNull = State->isNull(V1); + ConditionTruthVal V2IsNull = State->isNull(V2); + bool IsConstrained = true; + + // Check cases 'NULL + x' and 'NULL - x' + if (T1->isPointerType() && T2->isIntegerType()) { + if (!V1IsNull.isConstrainedTrue() || V2IsNull.isConstrainedTrue()) + return; + IsConstrained = V2IsNull.isConstrainedFalse(); + } + + // Check case 'x + NULL' + if (T1->isIntegerType() && T2->isPointerType()) { + if (V1IsNull.isConstrainedTrue() || !V2IsNull.isConstrainedTrue()) + return; + IsConstrained = V1IsNull.isConstrainedFalse(); + } + + // Check case 'NULL - p' or 'p - NULL' + if (T1->isPointerType() && T2->isPointerType()) { + if (!V1IsNull.isConstrainedTrue() && !V2IsNull.isConstrainedTrue()) + return; + if (V1IsNull.isConstrainedTrue() && V2IsNull.isConstrainedTrue()) + return; + IsConstrained = + V1IsNull.isConstrainedFalse() || V2IsNull.isConstrainedFalse(); + } + + SmallString<100> Buf; + llvm::raw_svector_ostream Out(Buf); + SmallVector<SourceRange, 2> Ranges; + + auto AddSubExprStr = [&](const Expr *E, bool IsPointer, + ConditionTruthVal IsNull) { + if (IsNull.isConstrainedTrue()) { + if (IsPointer) + Out << "null pointer"; + else + Out << "zero"; + } else { + if (!IsNull.isConstrainedFalse()) + Out << "probably "; + if (IsPointer) + Out << "non-null pointer"; + else + Out << "nonzero integer value"; + } + if (IsPointer) + AddDerefSource(Out, Ranges, E, State.get(), C.getLocationContext(), + false); + }; + + if (Op->getOpcode() == BO_Add) + Out << "Addition of a "; + else + Out << "Subtraction of a "; + AddSubExprStr(E1, T1->isPointerType(), V1IsNull); + Out << " and a "; + AddSubExprStr(E2, T2->isPointerType(), V2IsNull); + + if (IsConstrained) + Out << " results "; + else + Out << " may result "; + Out << "in undefined behavior"; + + ExplodedNode *N = C.generateErrorNode(State); + if (!N) + return; + auto BR = std::make_unique<PathSensitiveBugReport>(NullPointerArithmBug, + Buf.str(), N); + + if (T1->isPointerType()) + bugreporter::trackExpressionValue(N, E1, *BR); + if (T2->isPointerType()) + bugreporter::trackExpressionValue(N, E2, *BR); + + for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), + E = Ranges.end(); + I != E; ++I) + BR->addRange(*I); ---------------- steakhal wrote:
Why not a ranged-for here? https://github.com/llvm/llvm-project/pull/157129 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits