diff options
author | Gabor Marton <gabor.marton@ericsson.com> | 2020-09-03 13:23:49 +0200 |
---|---|---|
committer | Gabor Marton <gabor.marton@ericsson.com> | 2020-09-15 16:35:39 +0200 |
commit | a012bc4c42e4408a18e4c4d67306b79c576df961 (patch) | |
tree | e6b953bba529bb408767f221e515a9ba07baf05d /clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp | |
parent | e328456a9e6fa8c1ef05e183c1506ed837005847 (diff) | |
download | llvm-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.cpp | 59 |
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)}); |