Author: Balázs Kéri Date: 2023-11-14T10:58:05+01:00 New Revision: 41fe5c9a08f585a548ccf917804d67c79abcd3c3
URL: https://github.com/llvm/llvm-project/commit/41fe5c9a08f585a548ccf917804d67c79abcd3c3 DIFF: https://github.com/llvm/llvm-project/commit/41fe5c9a08f585a548ccf917804d67c79abcd3c3.diff LOG: [clang][analyzer] Improve StdLibraryFunctionsChecker 'readlink' modeling. (#71373) The functions 'readlink' and 'readlinkat' do return 0 only if the 'bufsize' argument is 0. Added: Modified: clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp clang/test/Analysis/std-c-library-functions-POSIX.c clang/test/Analysis/std-c-library-functions-path-notes.c Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 13bb9cef5e490ed..54a41b8bd7843dd 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -2865,9 +2865,14 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) - .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), - ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))}, + .Case({ArgumentCondition(2, WithinRange, Range(1, IntMax)), + ReturnValueCondition(LessThanOrEq, ArgNo(2)), + ReturnValueCondition(WithinRange, Range(1, Ssize_tMax))}, ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({ArgumentCondition(2, WithinRange, SingleValue(0)), + ReturnValueCondition(WithinRange, SingleValue(0))}, + ErrnoMustNotBeChecked, + "Assuming that argument 'bufsize' is 0") .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg) .ArgConstraint(NotNull(ArgNo(0))) .ArgConstraint(NotNull(ArgNo(1))) @@ -2884,9 +2889,14 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) - .Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)), - ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))}, + .Case({ArgumentCondition(3, WithinRange, Range(1, IntMax)), + ReturnValueCondition(LessThanOrEq, ArgNo(3)), + ReturnValueCondition(WithinRange, Range(1, Ssize_tMax))}, ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({ArgumentCondition(3, WithinRange, SingleValue(0)), + ReturnValueCondition(WithinRange, SingleValue(0))}, + ErrnoMustNotBeChecked, + "Assuming that argument 'bufsize' is 0") .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg) .ArgConstraint(ValidFileDescriptorOrAtFdcwd(ArgNo(0))) .ArgConstraint(NotNull(ArgNo(1))) diff --git a/clang/test/Analysis/std-c-library-functions-POSIX.c b/clang/test/Analysis/std-c-library-functions-POSIX.c index 84ce0f21e569fb5..daa4d904c3ac5ed 100644 --- a/clang/test/Analysis/std-c-library-functions-POSIX.c +++ b/clang/test/Analysis/std-c-library-functions-POSIX.c @@ -205,3 +205,23 @@ void test_sendmsg(int sockfd, const struct msghdr *msg, int flags) { ssize_t Ret = sendmsg(sockfd, msg, flags); clang_analyzer_eval(Ret != 0); // expected-warning{{TRUE}} } + +void test_readlink_bufsize_zero(char *Buf, size_t Bufsize) { + ssize_t Ret = readlink("path", Buf, Bufsize); + if (Ret == 0) + clang_analyzer_eval(Bufsize == 0); // expected-warning{{TRUE}} + else if (Ret > 0) + clang_analyzer_eval(Bufsize == 0); // expected-warning{{FALSE}} + else + clang_analyzer_eval(Bufsize == 0); // expected-warning{{UNKNOWN}} +} + +void test_readlinkat_bufsize_zero(int fd, char *Buf, size_t Bufsize) { + ssize_t Ret = readlinkat(fd, "path", Buf, Bufsize); + if (Ret == 0) + clang_analyzer_eval(Bufsize == 0); // expected-warning{{TRUE}} + else if (Ret > 0) + clang_analyzer_eval(Bufsize == 0); // expected-warning{{FALSE}} + else + clang_analyzer_eval(Bufsize == 0); // expected-warning{{UNKNOWN}} +} diff --git a/clang/test/Analysis/std-c-library-functions-path-notes.c b/clang/test/Analysis/std-c-library-functions-path-notes.c index d0957483c1391ad..4df00fe1e60646f 100644 --- a/clang/test/Analysis/std-c-library-functions-path-notes.c +++ b/clang/test/Analysis/std-c-library-functions-path-notes.c @@ -80,3 +80,12 @@ int test_fileno_arg_note(FILE *f1) { // expected-note{{The 1st argument to 'dup' is < 0 but should be >= 0}} \ // expected-note{{Assuming that 'fileno' fails}} } + +int test_readlink_bufsize_zero(char *Buf, size_t Bufsize) { + ssize_t Ret = readlink("path", Buf, Bufsize); // \ + // expected-note{{Assuming that argument 'bufsize' is 0}} \ + // expected-note{{'Ret' initialized here}} + return 1 / Ret; // \ + // expected-warning{{Division by zero}} \ + // expected-note{{Division by zero}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits