Author: Balázs Kéri Date: 2026-01-19T09:33:59+01:00 New Revision: dc26c7e14d49b41302fb260c269d1dd919bb48b5
URL: https://github.com/llvm/llvm-project/commit/dc26c7e14d49b41302fb260c269d1dd919bb48b5 DIFF: https://github.com/llvm/llvm-project/commit/dc26c7e14d49b41302fb260c269d1dd919bb48b5.diff LOG: [clang][analyzer] StdLibraryFunctionsChecker getcwd fix (#175794) `StdLibraryFunctionsChecker` contained the following condition for `getcwd`: ``` .Case({NotNull(0), ArgumentCondition(1, WithinRange, Range(1, SizeMax)), ReturnValueCondition(BO_EQ, ArgNo(0))}, ErrnoMustNotBeChecked, GenericSuccessMsg) ``` In this case argument 1 should be not zero and return value is set to be equal to argument 1. This would mean that return value is implicitly not zero. But for unknown reason (probably analyzer inaccuracy) it can occur that the return value is still assumable to be zero after this condition was applied. This results in false positive if `ErrnoChecker` is enabled because when the return value is 0 value of `errno` should be allowed to be read but in this case it is not. The bug is fixed by adding an extra (theoretically redundant) condition for the return value to be non-zero. Fixes #175136 Added: clang/test/Analysis/std-c-library-functions-char-uchar-conv.c Modified: clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 844447f59f7f6..8a3ee4443eb16 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -2277,7 +2277,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Signature(ArgTypes{CharPtrRestrictTy, IntTy, FilePtrRestrictTy}, RetType{CharPtrTy}), Summary(NoEvalCall) - .Case({ReturnValueCondition(BO_EQ, ArgNo(0))}, + .Case({NotNull(Ret), ReturnValueCondition(BO_EQ, ArgNo(0))}, ErrnoMustNotBeChecked, GenericSuccessMsg) .Case({IsNull(Ret)}, ErrnoIrrelevant, GenericFailureMsg) .ArgConstraint(NotNull(ArgNo(0))) @@ -2645,7 +2645,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( addToFunctionSummaryMap( "mkdtemp", Signature(ArgTypes{CharPtrTy}, RetType{CharPtrTy}), Summary(NoEvalCall) - .Case({ReturnValueCondition(BO_EQ, ArgNo(0))}, + .Case({NotNull(Ret), ReturnValueCondition(BO_EQ, ArgNo(0))}, ErrnoMustNotBeChecked, GenericSuccessMsg) .Case({IsNull(Ret)}, ErrnoNEZeroIrrelevant, GenericFailureMsg) .ArgConstraint(NotNull(ArgNo(0)))); @@ -2657,7 +2657,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Summary(NoEvalCall) .Case({NotNull(0), ArgumentCondition(1, WithinRange, Range(1, SizeMax)), - ReturnValueCondition(BO_EQ, ArgNo(0))}, + ReturnValueCondition(BO_EQ, ArgNo(0)), NotNull(Ret)}, ErrnoMustNotBeChecked, GenericSuccessMsg) .Case({NotNull(0), ArgumentCondition(1, WithinRange, SingleValue(0)), diff --git a/clang/test/Analysis/std-c-library-functions-char-uchar-conv.c b/clang/test/Analysis/std-c-library-functions-char-uchar-conv.c new file mode 100644 index 0000000000000..0c70ae9a13dee --- /dev/null +++ b/clang/test/Analysis/std-c-library-functions-char-uchar-conv.c @@ -0,0 +1,50 @@ +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=core,unix.StdCLibraryFunctions,unix.Errno \ +// RUN: -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true \ +// RUN: -verify %s +// +// expected-no-diagnostics + +#include "Inputs/errno_var.h" + +typedef __typeof__(sizeof(int)) size_t; +typedef struct {} FILE; +char *getcwd(char *buf, size_t size); +char *fgets(char *restrict s, int n, FILE *restrict stream); +char *mkdtemp(char *template); + +int fputc(int c, FILE *stream); +#define EOF (-1) + +void gh_175136(char *CharData, unsigned char *UCharData, size_t Size) { + if (!getcwd(CharData, Size)) { + if (errno == 2) { + return; + } + } + + if (!getcwd((char*)UCharData, Size)) { + if (errno == 2) { // Previously there was a (false) warning from unix.Errno on this line + return; + } + } +} + +void fgets_test(unsigned char *Buf, size_t Size, FILE *F) { + if (!fgets((char *)Buf, Size, F)) + if (errno == 1) // Similar case for the (false) warning + return; +} + +void mkdtemp_test(unsigned char *Buf) { + if (!mkdtemp((char *)Buf)) + if (errno == 1) // Similar case for the (false) warning + return; +} + +void fputc_test(long long c, FILE *stream) { + if (fputc((int)c, stream) == EOF) { + if (errno == 1) // This case did not produce the false warning + return; + } +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
