[clang][analyzer] Refine modeling of 'getcwd' in StdCLibraryFunctions checker (#141076)
Add extra branches for the case when the buffer argument is NULL. Fixes #135720
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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}}
|
||||
|
||||
Reference in New Issue
Block a user