[clang] [clang][analyzer] Refine modeling of 'getcwd' in StdCLibraryFunctions checker (PR #141076)
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Thu May 22 07:46:42 PDT 2025
https://github.com/balazske created https://github.com/llvm/llvm-project/pull/141076
Add extra branches for the case when the buffer argument is NULL.
>From a82a775585ea473d6c29457b260848436071d0ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.keri at ericsson.com>
Date: Thu, 22 May 2025 16:41:46 +0200
Subject: [PATCH] [clang][analyzer] Refine modeling of 'getcwd' in
StdCLibraryFunctions checker
Add extra branches for the case when the buffer argument is NULL.
---
.../Checkers/StdLibraryFunctionsChecker.cpp | 14 ++++++++++----
clang/test/Analysis/errno-stdlibraryfunctions.c | 15 ++++++++++++++-
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 3c6c3123f5cdd..6dae817fe89b5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -2651,16 +2651,22 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
addToFunctionSummaryMap(
"getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}),
Summary(NoEvalCall)
- .Case({ArgumentCondition(1, WithinRange, Range(1, SizeMax)),
+ .Case({NotNull(0),
+ ArgumentCondition(1, WithinRange, Range(1, SizeMax)),
ReturnValueCondition(BO_EQ, ArgNo(0))},
ErrnoMustNotBeChecked, GenericSuccessMsg)
- .Case({ArgumentCondition(1, WithinRange, SingleValue(0)),
+ .Case({NotNull(0),
+ ArgumentCondition(1, WithinRange, SingleValue(0)),
IsNull(Ret)},
ErrnoNEZeroIrrelevant, "Assuming that argument 'size' is 0")
- .Case({ArgumentCondition(1, WithinRange, Range(1, SizeMax)),
+ .Case({NotNull(0),
+ ArgumentCondition(1, WithinRange, Range(1, SizeMax)),
IsNull(Ret)},
ErrnoNEZeroIrrelevant, GenericFailureMsg)
- .ArgConstraint(NotNull(ArgNo(0)))
+ .Case({IsNull(0), NotNull(Ret)}, ErrnoMustNotBeChecked,
+ GenericSuccessMsg)
+ .Case({IsNull(0), IsNull(Ret)}, ErrnoNEZeroIrrelevant,
+ GenericFailureMsg)
.ArgConstraint(
BufferSize(/*Buffer*/ ArgNo(0), /*BufSize*/ ArgNo(1)))
.ArgConstraint(
diff --git a/clang/test/Analysis/errno-stdlibraryfunctions.c b/clang/test/Analysis/errno-stdlibraryfunctions.c
index 657aa37a42670..72d167f68a1f4 100644
--- a/clang/test/Analysis/errno-stdlibraryfunctions.c
+++ b/clang/test/Analysis/errno-stdlibraryfunctions.c
@@ -99,7 +99,9 @@ void errno_mkdtemp3(CHAR_PTR template) {
}
}
-void errno_getcwd(char *Buf, size_t Sz) {
+void errno_getcwd_buf_nonnull(char *Buf, size_t Sz) {
+ if (Buf == NULL)
+ return;
char *Path = getcwd(Buf, Sz);
if (Sz == 0) {
clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
@@ -114,6 +116,17 @@ void errno_getcwd(char *Buf, size_t Sz) {
}
}
+void errno_getcwd_buf_null() {
+ // POSIX does not mention this case but many implementations (Linux, FreeBSD) work this way.
+ char *Path = getcwd(NULL, 1);
+ if (Path == NULL) {
+ clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
+ if (errno) {} // no warning
+ } else {
+ if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
+ }
+}
+
void errno_execv(char *Path, char * Argv[]) {
int Ret = execv(Path, Argv);
clang_analyzer_eval(Ret == -1); // expected-warning{{TRUE}}
More information about the cfe-commits
mailing list