From 7dd20637c801b429f2dd1040941d00141459d64e Mon Sep 17 00:00:00 2001 From: Ben Shi <2283975856@qq.com> Date: Tue, 9 Jan 2024 09:27:57 +0800 Subject: [PATCH] Improve modeling of 'getcwd' in the StdLibraryFunctionsChecker (#77040) 1. Improve the 'errno' modeling. 2. Improve constraints of the arguments. --- clang/docs/ReleaseNotes.rst | 5 +++-- .../Checkers/StdLibraryFunctionsChecker.cpp | 13 ++++++++++++- clang/test/Analysis/errno-stdlibraryfunctions.c | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c9b577bd549b1e..803eb2f7c74cf6 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1150,9 +1150,10 @@ Improvements ^^^^^^^^^^^^ - Improved the ``unix.StdCLibraryFunctions`` checker by modeling more - functions like ``send``, ``recv``, ``readlink``, ``fflush``, ``mkdtemp`` and - ``errno`` behavior. + functions like ``send``, ``recv``, ``readlink``, ``fflush``, ``mkdtemp``, + ``getcwd`` and ``errno`` behavior. (`52ac71f92d38 `_, + `#77040 `_, `#76671 `_, `#71373 `_, `#76557 `_, diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 20068653d530a3..034825d88a44de 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -2516,10 +2516,21 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( .ArgConstraint(NotNull(ArgNo(0)))); // char *getcwd(char *buf, size_t size); - // FIXME: Improve for errno modeling. addToFunctionSummaryMap( "getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}), Summary(NoEvalCall) + .Case({ArgumentCondition(1, WithinRange, Range(1, SizeMax)), + ReturnValueCondition(BO_EQ, ArgNo(0))}, + ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({ArgumentCondition(1, WithinRange, SingleValue(0)), + IsNull(Ret)}, + ErrnoNEZeroIrrelevant, "Assuming that argument 'size' is 0") + .Case({ArgumentCondition(1, WithinRange, Range(1, SizeMax)), + IsNull(Ret)}, + ErrnoNEZeroIrrelevant, GenericFailureMsg) + .ArgConstraint(NotNull(ArgNo(0))) + .ArgConstraint( + BufferSize(/*Buffer*/ ArgNo(0), /*BufSize*/ ArgNo(1))) .ArgConstraint( ArgumentCondition(1, WithinRange, Range(0, SizeMax)))); diff --git a/clang/test/Analysis/errno-stdlibraryfunctions.c b/clang/test/Analysis/errno-stdlibraryfunctions.c index 80e14c4e2923ca..9e3d07e7aa88a0 100644 --- a/clang/test/Analysis/errno-stdlibraryfunctions.c +++ b/clang/test/Analysis/errno-stdlibraryfunctions.c @@ -74,3 +74,18 @@ void errno_mkdtemp(char *template) { if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} } } + +void errno_getcwd(char *Buf, size_t Sz) { + char *Path = getcwd(Buf, Sz); + if (Sz == 0) { + clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} + clang_analyzer_eval(Path == NULL); // expected-warning{{TRUE}} + if (errno) {} // no warning + } else if (Path == NULL) { + clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} + if (errno) {} // no warning + } else { + clang_analyzer_eval(Path == Buf); // expected-warning{{TRUE}} + if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} + } +}