aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
diff options
context:
space:
mode:
authorBalázs Kéri <1.int32@gmail.com>2023-05-16 09:05:44 +0200
committerBalázs Kéri <balazs.keri@ericsson.com>2023-05-16 09:28:14 +0200
commit258c9bebbdfa793493b71db555f5deb5ade499b4 (patch)
treef1161d881b0c5deba173f65ab7702225112c5cc1 /clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
parent6c06a079365db7bdf579b52a5ea1b6ba4a947611 (diff)
downloadllvm-258c9bebbdfa793493b71db555f5deb5ade499b4.zip
llvm-258c9bebbdfa793493b71db555f5deb5ade499b4.tar.gz
llvm-258c9bebbdfa793493b71db555f5deb5ade499b4.tar.bz2
[clang][analyzer] Handle special value AT_FDCWD in affected standard functions
Some file and directory related functions have an integer file descriptor argument that can be a valid file descriptor or a special value AT_FDCWD. This value is relatively often used in open source projects and is usually defined as a negative number, and the checker reports false warnings (a valid file descriptor is not negative) if this fix is not included. Reviewed By: steakhal Differential Revision: https://reviews.llvm.org/D149160
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp41
1 files changed, 25 insertions, 16 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 4e3ea09..ef85d60 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -1392,6 +1392,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
SValBuilder &SVB = C.getSValBuilder();
BasicValueFactory &BVF = SVB.getBasicValueFactory();
const ASTContext &ACtx = BVF.getContext();
+ Preprocessor &PP = C.getPreprocessor();
// Helper class to lookup a type by its name.
class LookupType {
@@ -1527,14 +1528,11 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
const RangeInt UCharRangeMax =
std::min(BVF.getMaxValue(ACtx.UnsignedCharTy).getLimitedValue(), IntMax);
- // The platform dependent value of EOF.
- // Try our best to parse this from the Preprocessor, otherwise fallback to -1.
- const auto EOFv = [&C]() -> RangeInt {
- if (const std::optional<int> OptInt =
- tryExpandAsInteger("EOF", C.getPreprocessor()))
- return *OptInt;
- return -1;
- }();
+ // Get platform dependent values of some macros.
+ // Try our best to parse this from the Preprocessor, otherwise fallback to a
+ // default value (what is found in a library header).
+ const auto EOFv = tryExpandAsInteger("EOF", PP).value_or(-1);
+ const auto AT_FDCWDv = tryExpandAsInteger("AT_FDCWD", PP).value_or(-100);
// Auxiliary class to aid adding summaries to the summary map.
struct AddToFunctionSummaryMap {
@@ -1979,6 +1977,12 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, IntMax))};
const auto &ReturnsValidFileDescriptor = ReturnsNonnegative;
+ auto ValidFileDescriptorOrAtFdcwd = [&](ArgNo ArgN) {
+ return std::make_shared<RangeConstraint>(
+ ArgN, WithinRange, Range({AT_FDCWDv, AT_FDCWDv}, {0, IntMax}),
+ "a valid file descriptor or AT_FDCWD");
+ };
+
// FILE *fopen(const char *restrict pathname, const char *restrict mode);
addToFunctionSummaryMap(
"fopen",
@@ -2130,6 +2134,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Summary(NoEvalCall)
.Case(ReturnsZero, ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1))));
// int dup(int fildes);
@@ -2207,7 +2212,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
.Case(ReturnsZero, ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
.ArgConstraint(NotNull(ArgNo(0)))
- .ArgConstraint(ArgumentCondition(1, WithinRange, Range(0, IntMax)))
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(1)))
.ArgConstraint(NotNull(ArgNo(2))));
// int lockf(int fd, int cmd, off_t len);
@@ -2318,6 +2323,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Summary(NoEvalCall)
.Case(ReturnsZero, ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1))));
std::optional<QualType> Dev_tTy = lookupTy("dev_t");
@@ -2339,6 +2345,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Summary(NoEvalCall)
.Case(ReturnsZero, ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1))));
// int chmod(const char *path, mode_t mode);
@@ -2357,7 +2364,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Summary(NoEvalCall)
.Case(ReturnsZero, ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
- .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1))));
// int fchmod(int fildes, mode_t mode);
@@ -2381,7 +2388,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Summary(NoEvalCall)
.Case(ReturnsZero, ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
- .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1))));
// int chown(const char *path, uid_t owner, gid_t group);
@@ -2446,9 +2453,9 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Summary(NoEvalCall)
.Case(ReturnsZero, ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
- .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1)))
- .ArgConstraint(ArgumentCondition(2, WithinRange, Range(0, IntMax)))
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(2)))
.ArgConstraint(NotNull(ArgNo(3))));
// int unlink(const char *pathname);
@@ -2466,7 +2473,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Summary(NoEvalCall)
.Case(ReturnsZero, ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
- .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1))));
std::optional<QualType> StructStatTy = lookupTy("stat");
@@ -2515,7 +2522,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Summary(NoEvalCall)
.Case(ReturnsZero, ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
- .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1)))
.ArgConstraint(NotNull(ArgNo(2))));
@@ -2690,7 +2697,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
- .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1)))
.ArgConstraint(NotNull(ArgNo(2)))
.ArgConstraint(BufferSize(/*Buffer=*/ArgNo(2),
@@ -2707,7 +2714,9 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Summary(NoEvalCall)
.Case(ReturnsZero, ErrnoMustNotBeChecked)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1)))
+ .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(2)))
.ArgConstraint(NotNull(ArgNo(3))));
// char *realpath(const char *restrict file_name,