diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -457,6 +457,10 @@ CaseConstraints.push_back(std::move(CS)); return *this; } + Summary &Case(const ConstraintSet &CS) { + CaseConstraints.push_back(CS); + return *this; + } Summary &ArgConstraint(ValueConstraintPtr VC) { assert(VC->getArgNo() != Ret && "Arg constraint should not refer to the return value"); @@ -1235,9 +1239,8 @@ // read()-like functions that never return more than buffer size. auto FreadSummary = Summary(NoEvalCall) - .Case({ - ReturnValueCondition(LessThanOrEq, ArgNo(2)), - }) + .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), + ReturnValueCondition(WithinRange, Range(0, SizeMax))}) .ArgConstraint(NotNull(ArgNo(0))) .ArgConstraint(NotNull(ArgNo(3))) .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1), @@ -1764,6 +1767,8 @@ Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) + .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), + ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) .ArgConstraint(NotNull(ArgNo(0))) .ArgConstraint(NotNull(ArgNo(1))) .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), @@ -1779,6 +1784,8 @@ ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) + .Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)), + ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(NotNull(ArgNo(1))) .ArgConstraint(NotNull(ArgNo(2))) @@ -1842,6 +1849,9 @@ Optional Socklen_tPtrRestrictTy = getRestrictTy(Socklen_tPtrTy); Optional Socklen_tMax = getMaxValue(Socklen_tTy); + const auto ReturnsZeroOrMinusOne = + ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))}; + // In 'socket.h' of some libc implementations with C99, sockaddr parameter // is a transparent union of the underlying sockaddr_ family of pointers // instead of being a pointer to struct sockaddr. In these cases, the @@ -1850,6 +1860,7 @@ // constraints which require pointer types for the sockaddr param. auto Accept = Summary(NoEvalCall) + .Case({ReturnValueCondition(WithinRange, Range(-1, IntMax))}) .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))); if (!addToFunctionSummaryMap( "accept", @@ -1872,6 +1883,7 @@ Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(NotNull(ArgNo(1))) @@ -1884,6 +1896,7 @@ "bind", Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint( @@ -1897,6 +1910,7 @@ Socklen_tPtrRestrictTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(NotNull(ArgNo(1))) @@ -1906,6 +1920,7 @@ Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax)))); @@ -1917,6 +1932,7 @@ Socklen_tPtrRestrictTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(NotNull(ArgNo(1))) @@ -1926,6 +1942,7 @@ Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax)))); @@ -1936,6 +1953,7 @@ Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(NotNull(ArgNo(1))))) @@ -1943,11 +1961,14 @@ "connect", Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax)))); auto Recvfrom = Summary(NoEvalCall) + .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), + ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2))); @@ -1971,6 +1992,8 @@ auto Sendto = Summary(NoEvalCall) + .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), + ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2))); @@ -1994,6 +2017,7 @@ addToFunctionSummaryMap("listen", Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint(ArgumentCondition( 0, WithinRange, Range(0, IntMax)))); @@ -2003,6 +2027,8 @@ Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy, IntTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) + .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), + ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2)))); @@ -2013,12 +2039,14 @@ getPointerTy(getConstTy(StructMsghdrTy)); // ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); - addToFunctionSummaryMap("recvmsg", - Signature(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy}, - RetType{Ssize_tTy}), - Summary(NoEvalCall) - .ArgConstraint(ArgumentCondition( - 0, WithinRange, Range(0, IntMax)))); + addToFunctionSummaryMap( + "recvmsg", + Signature(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy}, + RetType{Ssize_tTy}), + Summary(NoEvalCall) + .Case({ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) + .ArgConstraint( + ArgumentCondition(0, WithinRange, Range(0, IntMax)))); // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); addToFunctionSummaryMap( @@ -2026,6 +2054,7 @@ Signature(ArgTypes{IntTy, ConstStructMsghdrPtrTy, IntTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) + .Case({ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax)))); @@ -2036,6 +2065,7 @@ Signature(ArgTypes{IntTy, IntTy, IntTy, ConstVoidPtrTy, Socklen_tTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint(NotNull(ArgNo(3))) .ArgConstraint( BufferSize(/*Buffer=*/ArgNo(3), /*BufSize=*/ArgNo(4))) @@ -2051,6 +2081,7 @@ Socklen_tPtrRestrictTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint(NotNull(ArgNo(3))) .ArgConstraint(NotNull(ArgNo(4)))); @@ -2060,6 +2091,8 @@ Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) + .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), + ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2)))); @@ -2068,7 +2101,9 @@ addToFunctionSummaryMap( "socketpair", Signature(ArgTypes{IntTy, IntTy, IntTy, IntPtrTy}, RetType{IntTy}), - Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(3)))); + Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) + .ArgConstraint(NotNull(ArgNo(3)))); // int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, // char *restrict node, socklen_t nodelen,