Author: Balázs Kéri Date: 2025-05-23T09:26:31+02:00 New Revision: be50ada9d008673a041a5e675f9d9d70a4572aaa
URL: https://github.com/llvm/llvm-project/commit/be50ada9d008673a041a5e675f9d9d70a4572aaa DIFF: https://github.com/llvm/llvm-project/commit/be50ada9d008673a041a5e675f9d9d70a4572aaa.diff LOG: [clang][analyzer] Refine modeling of 'getcwd' in StdCLibraryFunctions checker (#141076) Add extra branches for the case when the buffer argument is NULL. Fixes #135720 Added: Modified: clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp clang/test/Analysis/errno-stdlibraryfunctions.c Removed: ################################################################################ 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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits