aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
diff options
context:
space:
mode:
authorGabor Marton <gabor.marton@ericsson.com>2020-09-03 13:23:49 +0200
committerGabor Marton <gabor.marton@ericsson.com>2020-09-15 16:35:39 +0200
commita012bc4c42e4408a18e4c4d67306b79c576df961 (patch)
treee6b953bba529bb408767f221e515a9ba07baf05d /clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
parente328456a9e6fa8c1ef05e183c1506ed837005847 (diff)
downloadllvm-a012bc4c42e4408a18e4c4d67306b79c576df961.zip
llvm-a012bc4c42e4408a18e4c4d67306b79c576df961.tar.gz
llvm-a012bc4c42e4408a18e4c4d67306b79c576df961.tar.bz2
[analyzer][StdLibraryFunctionsChecker] Elaborate the summary of fread and fwrite
Add the BufferSize argument constraint to fread and fwrite. This change itself makes it possible to discover a security critical case, described in SEI-CERT ARR38-C. We also add the not-null constraint on the 3rd arguments. In this patch, I also remove those lambdas that don't take any parameters (Fwrite, Fread, Getc), thus making the code better structured. Differential Revision: https://reviews.llvm.org/D87081
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp59
1 files changed, 32 insertions, 27 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index f5ad809..45711ca 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -1090,35 +1090,12 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Optional<QualType> FilePtrRestrictTy = getRestrictTy(FilePtrTy);
// Templates for summaries that are reused by many functions.
- auto Getc = [&]() {
- return Summary(ArgTypes{FilePtrTy}, RetType{IntTy}, NoEvalCall)
- .Case({ReturnValueCondition(WithinRange,
- {{EOFv, EOFv}, {0, UCharRangeMax}})});
- };
auto Read = [&](RetType R, RangeInt Max) {
return Summary(ArgTypes{Irrelevant, Irrelevant, SizeTy}, RetType{R},
NoEvalCall)
.Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
ReturnValueCondition(WithinRange, Range(-1, Max))});
};
- auto Fread = [&]() {
- return Summary(
- ArgTypes{VoidPtrRestrictTy, SizeTy, SizeTy, FilePtrRestrictTy},
- RetType{SizeTy}, NoEvalCall)
- .Case({
- ReturnValueCondition(LessThanOrEq, ArgNo(2)),
- })
- .ArgConstraint(NotNull(ArgNo(0)));
- };
- auto Fwrite = [&]() {
- return Summary(ArgTypes{ConstVoidPtrRestrictTy, SizeTy, SizeTy,
- FilePtrRestrictTy},
- RetType{SizeTy}, NoEvalCall)
- .Case({
- ReturnValueCondition(LessThanOrEq, ArgNo(2)),
- })
- .ArgConstraint(NotNull(ArgNo(0)));
- };
auto Getline = [&](RetType R, RangeInt Max) {
return Summary(ArgTypes{Irrelevant, Irrelevant, Irrelevant}, RetType{R},
NoEvalCall)
@@ -1283,19 +1260,45 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
// The getc() family of functions that returns either a char or an EOF.
- addToFunctionSummaryMap("getc", Getc());
- addToFunctionSummaryMap("fgetc", Getc());
+ addToFunctionSummaryMap(
+ {"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
+ Summary(NoEvalCall)
+ .Case({ReturnValueCondition(WithinRange,
+ {{EOFv, EOFv}, {0, UCharRangeMax}})}));
addToFunctionSummaryMap(
"getchar", Summary(ArgTypes{}, RetType{IntTy}, NoEvalCall)
.Case({ReturnValueCondition(
WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})}));
// read()-like functions that never return more than buffer size.
- addToFunctionSummaryMap("fread", Fread());
- addToFunctionSummaryMap("fwrite", Fwrite());
+ auto FreadSummary =
+ Summary(NoEvalCall)
+ .Case({
+ ReturnValueCondition(LessThanOrEq, ArgNo(2)),
+ })
+ .ArgConstraint(NotNull(ArgNo(0)))
+ .ArgConstraint(NotNull(ArgNo(3)))
+ .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
+ /*BufSizeMultiplier=*/ArgNo(2)));
+
+ // size_t fread(void *restrict ptr, size_t size, size_t nitems,
+ // FILE *restrict stream);
+ addToFunctionSummaryMap(
+ "fread",
+ Signature(ArgTypes{VoidPtrRestrictTy, SizeTy, SizeTy, FilePtrRestrictTy},
+ RetType{SizeTy}),
+ FreadSummary);
+ // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems,
+ // FILE *restrict stream);
+ addToFunctionSummaryMap("fwrite",
+ Signature(ArgTypes{ConstVoidPtrRestrictTy, SizeTy,
+ SizeTy, FilePtrRestrictTy},
+ RetType{SizeTy}),
+ FreadSummary);
// We are not sure how ssize_t is defined on every platform, so we
// provide three variants that should cover common cases.
+ // FIXME Use lookupTy("ssize_t") instead of the `Read` lambda.
// FIXME these are actually defined by POSIX and not by the C standard, we
// should handle them together with the rest of the POSIX functions.
addToFunctionSummaryMap("read", {Read(IntTy, IntMax), Read(LongTy, LongMax),
@@ -1304,11 +1307,13 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
Read(LongLongTy, LongLongMax)});
// getline()-like functions either fail or read at least the delimiter.
+ // FIXME Use lookupTy("ssize_t") instead of the `Getline` lambda.
// FIXME these are actually defined by POSIX and not by the C standard, we
// should handle them together with the rest of the POSIX functions.
addToFunctionSummaryMap("getline",
{Getline(IntTy, IntMax), Getline(LongTy, LongMax),
Getline(LongLongTy, LongLongMax)});
+ // FIXME getdelim's signature is different than getline's!
addToFunctionSummaryMap("getdelim",
{Getline(IntTy, IntMax), Getline(LongTy, LongMax),
Getline(LongLongTy, LongLongMax)});