================
@@ -2617,6 +2639,54 @@ void CStringChecker::evalStrsep(CheckerContext &C,
C.addTransition(State);
}
+void CStringChecker::evalStrchrCommon(CheckerContext &C, const CallEvent &Call,
+ StringRef FnName,
+ bool CanReturnNull) const {
+ CurrentFunctionDescription = FnName;
+ ProgramStateRef State = C.getState();
+ const StackFrame *SF = C.getStackFrame();
+ SValBuilder &SVB = C.getSValBuilder();
+ ASTContext &Ctx = C.getASTContext();
+ const Expr *CE = Call.getOriginExpr();
+ assert(CE);
+
+ // These functions always return a pointer.
+ if (!CE->getType()->isPointerType())
+ return;
+
+ // The first argument must be non-null for all functions in this family.
+ SourceArgExpr Src = {{Call.getArgExpr(0), 0}};
+ SVal SrcVal = State->getSVal(Src.Expression, SF);
+ State = checkNonNull(C, State, Src, SrcVal);
+ if (!State)
+ return;
+
+ // NULL (no-match) branch.
+ if (CanReturnNull) {
+ ProgramStateRef NullState =
+ State->BindExpr(CE, SF, SVB.makeNullWithType(CE->getType()));
+ C.addTransition(NullState);
+ }
+
+ // Found branch: a pointer within the source; needs a Loc for the arithmetic.
+ std::optional<Loc> SrcLoc = SrcVal.getAs<Loc>();
+ if (!SrcLoc) {
+ SVal Result = SVB.conjureSymbolVal(Call, C.blockCount());
+ State = State->BindExpr(CE, SF, Result);
+ C.addTransition(State);
+ return;
+ }
+
+ // The result is: Src + SymOffset
----------------
steakhal wrote:
Originally, I added a constraint on it using the dynamic extent as the upper
bound.
However, it didn't affect any of the tests, and I don't think it's a really
valuable constraint.
I'd say, let's revisit this once we have evidence for the utility. WDYT?
https://github.com/llvm/llvm-project/pull/207267
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits