================
@@ -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

Reply via email to