https://github.com/benshi001 updated https://github.com/llvm/llvm-project/pull/78895
>From 382ae9d692df575f47c203c9fff2036c42c4833b Mon Sep 17 00:00:00 2001 From: Ben Shi <benn...@tencent.com> Date: Sun, 21 Jan 2024 18:29:06 +0800 Subject: [PATCH 1/2] [clang][analyzer] Improve modeling of 'popen' and 'pclose' in StdLibraryFunctionsChecker --- .../Checkers/StdLibraryFunctionsChecker.cpp | 34 +++++++++++-------- .../Analysis/Inputs/system-header-simulator.h | 2 ++ .../Analysis/std-c-library-functions-POSIX.c | 4 +-- clang/test/Analysis/stream-errno.c | 25 ++++++++++++++ 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 61bf3c8528be2b..be26f5521c8d76 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -2204,6 +2204,16 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( .ArgConstraint(NotNull(ArgNo(1))) .ArgConstraint(NotNull(ArgNo(2)))); + // FILE *popen(const char *command, const char *type); + addToFunctionSummaryMap( + "popen", + Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{FilePtrTy}), + Summary(NoEvalCall) + .Case({NotNull(Ret)}, ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({IsNull(Ret)}, ErrnoNEZeroIrrelevant, GenericFailureMsg) + .ArgConstraint(NotNull(ArgNo(0))) + .ArgConstraint(NotNull(ArgNo(1)))); + // int fclose(FILE *stream); addToFunctionSummaryMap( "fclose", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), @@ -2212,6 +2222,15 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( .Case(ReturnsEOF, ErrnoNEZeroIrrelevant, GenericFailureMsg) .ArgConstraint(NotNull(ArgNo(0)))); + // int pclose(FILE *stream); + addToFunctionSummaryMap( + "pclose", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), + Summary(NoEvalCall) + .Case({ReturnValueCondition(WithinRange, {{0, IntMax}})}, + ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg) + .ArgConstraint(NotNull(ArgNo(0)))); + // int ungetc(int c, FILE *stream); addToFunctionSummaryMap( "ungetc", Signature(ArgTypes{IntTy, FilePtrTy}, RetType{IntTy}), @@ -2827,21 +2846,6 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax)))); - // FILE *popen(const char *command, const char *type); - // FIXME: Improve for errno modeling. - addToFunctionSummaryMap( - "popen", - Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{FilePtrTy}), - Summary(NoEvalCall) - .ArgConstraint(NotNull(ArgNo(0))) - .ArgConstraint(NotNull(ArgNo(1)))); - - // int pclose(FILE *stream); - // FIXME: Improve for errno modeling. - addToFunctionSummaryMap( - "pclose", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), - Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); - // int close(int fildes); addToFunctionSummaryMap( "close", Signature(ArgTypes{IntTy}, RetType{IntTy}), diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h b/clang/test/Analysis/Inputs/system-header-simulator.h index 96072741a8abc1..15986984802c0e 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator.h +++ b/clang/test/Analysis/Inputs/system-header-simulator.h @@ -48,7 +48,9 @@ FILE *fopen(const char *restrict path, const char *restrict mode); FILE *fdopen(int fd, const char *mode); FILE *tmpfile(void); FILE *freopen(const char *restrict pathname, const char *restrict mode, FILE *restrict stream); +FILE *popen(const char *command, const char *mode); int fclose(FILE *fp); +int pclose(FILE *stream); size_t fread(void *restrict, size_t, size_t, FILE *restrict); size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict); int fgetc(FILE *stream); diff --git a/clang/test/Analysis/std-c-library-functions-POSIX.c b/clang/test/Analysis/std-c-library-functions-POSIX.c index 51b136d9ba3567..03aa8e2e00a75d 100644 --- a/clang/test/Analysis/std-c-library-functions-POSIX.c +++ b/clang/test/Analysis/std-c-library-functions-POSIX.c @@ -20,7 +20,9 @@ // CHECK: Loaded summary for: FILE *fdopen(int fd, const char *mode) // CHECK: Loaded summary for: FILE *tmpfile(void) // CHECK: Loaded summary for: FILE *freopen(const char *restrict pathname, const char *restrict mode, FILE *restrict stream) +// CHECK: Loaded summary for: FILE *popen(const char *command, const char *type) // CHECK: Loaded summary for: int fclose(FILE *stream) +// CHECK: Loaded summary for: int pclose(FILE *stream) // CHECK: Loaded summary for: int fseek(FILE *stream, long offset, int whence) // CHECK: Loaded summary for: int fseeko(FILE *stream, off_t offset, int whence) // CHECK: Loaded summary for: off_t ftello(FILE *stream) @@ -74,8 +76,6 @@ // CHECK: Loaded summary for: DIR *opendir(const char *name) // CHECK: Loaded summary for: DIR *fdopendir(int fd) // CHECK: Loaded summary for: int isatty(int fildes) -// CHECK: Loaded summary for: FILE *popen(const char *command, const char *type) -// CHECK: Loaded summary for: int pclose(FILE *stream) // CHECK: Loaded summary for: int close(int fildes) // CHECK: Loaded summary for: long fpathconf(int fildes, int name) // CHECK: Loaded summary for: long pathconf(const char *path, int name) diff --git a/clang/test/Analysis/stream-errno.c b/clang/test/Analysis/stream-errno.c index fab6a58b3275a8..44bf949673082d 100644 --- a/clang/test/Analysis/stream-errno.c +++ b/clang/test/Analysis/stream-errno.c @@ -51,6 +51,17 @@ void check_freopen(void) { if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} } +void check_popen(void) { + FILE *F = popen("xxx", "r"); + if (!F) { + 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' [unix.Errno]}} + pclose(F); + } +} + void check_fclose(void) { FILE *F = tmpfile(); if (!F) @@ -64,6 +75,20 @@ void check_fclose(void) { if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} } +void check_pclose(void) { + FILE *F = popen("xx", "w"); + if (!F) + return; + int Ret = pclose(F); + if (Ret == -1) { + clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} + if (errno) {} // no-warning + } else { + clang_analyzer_eval(Ret >= 0); // expected-warning{{TRUE}} + if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} + } +} + void check_fread_size0(void) { char Buf[10]; FILE *F = tmpfile(); >From 8a57c1a2037e7ae31eb561318156a9231d899812 Mon Sep 17 00:00:00 2001 From: Ben Shi <benn...@tencent.com> Date: Thu, 25 Jan 2024 12:55:50 +0800 Subject: [PATCH 2/2] [clang][analyzer] Improve modeling of 'popen' and 'pclose' in StdLibraryFunctionsChecker --- .../test/Analysis/errno-stdlibraryfunctions.c | 25 +++++++++++++++++++ clang/test/Analysis/stream-errno.c | 25 ------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/clang/test/Analysis/errno-stdlibraryfunctions.c b/clang/test/Analysis/errno-stdlibraryfunctions.c index 7876bafc2eb210..9b487fed0a2eb8 100644 --- a/clang/test/Analysis/errno-stdlibraryfunctions.c +++ b/clang/test/Analysis/errno-stdlibraryfunctions.c @@ -103,3 +103,28 @@ void errno_execvp(char *File, char * Argv[]) { clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} if (errno) {} // no warning } + +void errno_popen(void) { + FILE *F = popen("xxx", "r"); + if (!F) { + 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' [unix.Errno]}} + pclose(F); + } +} + +void errno_pclose(void) { + FILE *F = popen("xx", "w"); + if (!F) + return; + int Ret = pclose(F); + if (Ret == -1) { + clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} + if (errno) {} // no-warning + } else { + clang_analyzer_eval(Ret >= 0); // expected-warning{{TRUE}} + if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} + } +} diff --git a/clang/test/Analysis/stream-errno.c b/clang/test/Analysis/stream-errno.c index 44bf949673082d..fab6a58b3275a8 100644 --- a/clang/test/Analysis/stream-errno.c +++ b/clang/test/Analysis/stream-errno.c @@ -51,17 +51,6 @@ void check_freopen(void) { if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} } -void check_popen(void) { - FILE *F = popen("xxx", "r"); - if (!F) { - 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' [unix.Errno]}} - pclose(F); - } -} - void check_fclose(void) { FILE *F = tmpfile(); if (!F) @@ -75,20 +64,6 @@ void check_fclose(void) { if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} } -void check_pclose(void) { - FILE *F = popen("xx", "w"); - if (!F) - return; - int Ret = pclose(F); - if (Ret == -1) { - clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} - if (errno) {} // no-warning - } else { - clang_analyzer_eval(Ret >= 0); // expected-warning{{TRUE}} - if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} - } -} - void check_fread_size0(void) { char Buf[10]; FILE *F = tmpfile(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits