================
@@ -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";
----------------
steakhal wrote:

I really wish we could simplify this. It's generally hard to predict the 
possible result string patterns due to the control-flow and stateful nature of 
such code.
I'd recommend thinking about how to make it more declarative.
For example, having ternaries usually makes the code terser, hence easier to 
put together the pieces.
Even better, having a string table, and just selecting the relevant pattern and 
filling the details using llvm::formatv.
Or something along the way.

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