[clang] 27d963a - [clang][analyzer] Improve modeling of 'fseeko' and 'ftello' in StdLibraryFunctionsChecker (#77902)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 16 00:58:11 PST 2024
Author: Ben Shi
Date: 2024-01-16T16:58:07+08:00
New Revision: 27d963a7089b050d402dbc1ae210d505f7affff6
URL: https://github.com/llvm/llvm-project/commit/27d963a7089b050d402dbc1ae210d505f7affff6
DIFF: https://github.com/llvm/llvm-project/commit/27d963a7089b050d402dbc1ae210d505f7affff6.diff
LOG: [clang][analyzer] Improve modeling of 'fseeko' and 'ftello' in StdLibraryFunctionsChecker (#77902)
Added:
Modified:
clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
clang/test/Analysis/std-c-library-functions-POSIX.c
clang/test/Analysis/stream-errno.c
Removed:
################################################################################
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 3b36565681a7f33..641ebe90f88e2eb 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -2220,6 +2220,9 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
0, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}}))
.ArgConstraint(NotNull(ArgNo(1))));
+ std::optional<QualType> Off_tTy = lookupTy("off_t");
+ std::optional<RangeInt> Off_tMax = getMaxValue(Off_tTy);
+
// int fseek(FILE *stream, long offset, int whence);
// FIXME: It can be possible to get the 'SEEK_' values (like EOFv) and use
// these for condition of arg 2.
@@ -2232,6 +2235,16 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
.ArgConstraint(NotNull(ArgNo(0)))
.ArgConstraint(ArgumentCondition(2, WithinRange, {{0, 2}})));
+ // int fseeko(FILE *stream, off_t offset, int whence);
+ addToFunctionSummaryMap(
+ "fseeko",
+ Signature(ArgTypes{FilePtrTy, Off_tTy, IntTy}, RetType{IntTy}),
+ Summary(NoEvalCall)
+ .Case(ReturnsZero, ErrnoMustNotBeChecked, GenericSuccessMsg)
+ .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
+ .ArgConstraint(NotNull(ArgNo(0)))
+ .ArgConstraint(ArgumentCondition(2, WithinRange, {{0, 2}})));
+
// int fgetpos(FILE *restrict stream, fpos_t *restrict pos);
// From 'The Open Group Base Specifications Issue 7, 2018 edition':
// "The fgetpos() function shall not change the setting of errno if
@@ -2279,6 +2292,15 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
.ArgConstraint(NotNull(ArgNo(0))));
+ // off_t ftello(FILE *stream);
+ addToFunctionSummaryMap(
+ "ftello", Signature(ArgTypes{FilePtrTy}, RetType{Off_tTy}),
+ Summary(NoEvalCall)
+ .Case({ReturnValueCondition(WithinRange, Range(0, Off_tMax))},
+ ErrnoMustNotBeChecked, GenericSuccessMsg)
+ .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
+ .ArgConstraint(NotNull(ArgNo(0))));
+
// int fileno(FILE *stream);
addToFunctionSummaryMap(
"fileno", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
@@ -2410,8 +2432,6 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
.ArgConstraint(
ArgumentCondition(0, WithinRange, Range(0, IntMax))));
- std::optional<QualType> Off_tTy = lookupTy("off_t");
-
// int truncate(const char *path, off_t length);
addToFunctionSummaryMap(
"truncate",
@@ -2854,19 +2874,6 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
"rand_r", Signature(ArgTypes{UnsignedIntPtrTy}, RetType{IntTy}),
Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
- // int fseeko(FILE *stream, off_t offset, int whence);
- addToFunctionSummaryMap(
- "fseeko",
- Signature(ArgTypes{FilePtrTy, Off_tTy, IntTy}, RetType{IntTy}),
- Summary(NoEvalCall)
- .Case(ReturnsZeroOrMinusOne, ErrnoIrrelevant)
- .ArgConstraint(NotNull(ArgNo(0))));
-
- // off_t ftello(FILE *stream);
- addToFunctionSummaryMap(
- "ftello", Signature(ArgTypes{FilePtrTy}, RetType{Off_tTy}),
- Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
-
// void *mmap(void *addr, size_t length, int prot, int flags, int fd,
// off_t offset);
// FIXME: Improve for errno modeling.
diff --git a/clang/test/Analysis/std-c-library-functions-POSIX.c b/clang/test/Analysis/std-c-library-functions-POSIX.c
index daa4d904c3ac5ed..8a26e0b0f27286f 100644
--- a/clang/test/Analysis/std-c-library-functions-POSIX.c
+++ b/clang/test/Analysis/std-c-library-functions-POSIX.c
@@ -21,6 +21,8 @@
// CHECK: Loaded summary for: FILE *freopen(const char *restrict pathname, const char *restrict mode, FILE *restrict stream)
// CHECK: Loaded summary for: int fclose(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)
// CHECK: Loaded summary for: int fileno(FILE *stream)
// CHECK: Loaded summary for: long a64l(const char *str64)
// CHECK: Loaded summary for: char *l64a(long value)
@@ -80,8 +82,6 @@
// CHECK: Loaded summary for: void rewinddir(DIR *dir)
// CHECK: Loaded summary for: void seekdir(DIR *dirp, long loc)
// CHECK: Loaded summary for: int rand_r(unsigned int *seedp)
-// CHECK: Loaded summary for: int fseeko(FILE *stream, off_t offset, int whence)
-// CHECK: Loaded summary for: off_t ftello(FILE *stream)
// CHECK: Loaded summary for: void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
// CHECK: Loaded summary for: void *mmap64(void *addr, size_t length, int prot, int flags, int fd, off64_t offset)
// CHECK: Loaded summary for: int pipe(int fildes[2])
diff --git a/clang/test/Analysis/stream-errno.c b/clang/test/Analysis/stream-errno.c
index f44ee6070708b26..13981e9094d1c98 100644
--- a/clang/test/Analysis/stream-errno.c
+++ b/clang/test/Analysis/stream-errno.c
@@ -129,6 +129,7 @@ void check_fseek(void) {
int S = fseek(F, 11, SEEK_SET);
if (S != 0) {
clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(S == -1); // expected-warning{{TRUE}}
if (errno) {} // no-warning
fclose(F);
return;
@@ -136,6 +137,21 @@ void check_fseek(void) {
if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
}
+void check_fseeko(void) {
+ FILE *F = tmpfile();
+ if (!F)
+ return;
+ int S = fseeko(F, 11, SEEK_SET);
+ if (S == -1) {
+ clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
+ if (errno) {} // no-warning
+ } else {
+ clang_analyzer_eval(S == 0); // expected-warning{{TRUE}}
+ if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
+ }
+ fclose(F);
+}
+
void check_no_errno_change(void) {
FILE *F = tmpfile();
if (!F)
@@ -197,6 +213,21 @@ void check_ftell(void) {
fclose(F);
}
+void check_ftello(void) {
+ FILE *F = tmpfile();
+ if (!F)
+ return;
+ off_t Ret = ftello(F);
+ if (Ret >= 0) {
+ if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
+ } else {
+ clang_analyzer_eval(Ret == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
+ if (errno) {} // no-warning
+ }
+ fclose(F);
+}
+
void check_rewind(void) {
FILE *F = tmpfile();
if (!F)
More information about the cfe-commits
mailing list