[clang] [clang][analyzer] Model `strxfrm` (PR #156507)
Balazs Benics via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 5 02:00:00 PDT 2025
Alejandro =?utf-8?q?Álvarez_Ayllón?=,
Alejandro =?utf-8?q?Álvarez_Ayllón?=,
Alejandro =?utf-8?q?Álvarez_Ayllón?=,
Alejandro =?utf-8?q?Álvarez_Ayllón?Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/156507 at github.com>
================
@@ -2243,6 +2246,109 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
C.addTransition(state);
}
+void CStringChecker::evalStrxfrm(CheckerContext &C,
+ const CallEvent &Call) const {
+ // size_t strxfrm(char *dest, const char *src, size_t n);
+ CurrentFunctionDescription = "locale transformation function";
+
+ ProgramStateRef State = C.getState();
+ const LocationContext *LCtx = C.getLocationContext();
+ SValBuilder &SVB = C.getSValBuilder();
+
+ // Get arguments
+ DestinationArgExpr Dest = {{Call.getArgExpr(0), 0}};
+ SourceArgExpr Source = {{Call.getArgExpr(1), 1}};
+ SizeArgExpr Size = {{Call.getArgExpr(2), 2}};
+
+ // `src` can never be null
+ SVal SrcVal = State->getSVal(Source.Expression, LCtx);
+ State = checkNonNull(C, State, Source, SrcVal);
+ if (!State)
+ return;
+
+ // Buffer must not overlap
+ State = CheckOverlap(C, State, Size, Dest, Source, CK_Regular);
+ if (!State)
+ return;
+
+ // The function returns an implementation-defined length needed for
+ // transformation
+ SVal RetVal = SVB.conjureSymbolVal(Call, C.blockCount());
+
+ // Check if size is zero
+ SVal SizeVal = State->getSVal(Size.Expression, LCtx);
+ QualType SizeTy = Size.Expression->getType();
+
+ auto [StateZeroSize, StateSizeNonZero] =
+ assumeZero(C, State, SizeVal, SizeTy);
+
+ // We can't assume anything about size, just bind the return value and be done
+ if (!StateZeroSize && !StateSizeNonZero) {
+ State = State->BindExpr(Call.getOriginExpr(), LCtx, RetVal);
+ C.addTransition(State);
----------------
steakhal wrote:
I'm worried about the maintainability of this code, that we need to remember to bind before transitioning.
Could we fuse these two together?
I was thinking of using a lambda bundling these two, or something like that.
https://github.com/llvm/llvm-project/pull/156507
More information about the cfe-commits
mailing list