[clang] ASTMatchers: Fix out-of-bounds access in foreachArgumentWithParamType.

The matcher crashes when a variadic function pointer is invoked because the
FunctionProtoType has fewer parameters than arguments.

Matching of non-variadic arguments now works.

Differential Revision: https://reviews.llvm.org/D114559

Reviewed-by: sammccall
This commit is contained in:
Felix Berger 2021-11-24 13:45:36 -05:00
parent 61521a5a3d
commit a1b1c23a3b
2 changed files with 26 additions and 1 deletions

View File

@ -4886,7 +4886,7 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParamType,
// This test is cheaper compared to the big matcher in the next if. // This test is cheaper compared to the big matcher in the next if.
// Therefore, please keep this order. // Therefore, please keep this order.
if (FProto) { if (FProto && FProto->getNumParams() > ParamIndex) {
QualType ParamType = FProto->getParamType(ParamIndex); QualType ParamType = FProto->getParamType(ParamIndex);
if (ParamMatcher.matches(ParamType, Finder, &ParamMatches)) { if (ParamMatcher.matches(ParamType, Finder, &ParamMatches)) {
Result.addMatch(ParamMatches); Result.addMatch(ParamMatches);

View File

@ -1094,6 +1094,31 @@ TEST(ForEachArgumentWithParamType, MatchesMemberFunctionPtrCalls) {
S, CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg"))); S, CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));
} }
TEST(ForEachArgumentWithParamType, MatchesVariadicFunctionPtrCalls) {
StatementMatcher ArgumentY =
declRefExpr(to(varDecl(hasName("y")))).bind("arg");
TypeMatcher IntType = qualType(builtinType()).bind("type");
StatementMatcher CallExpr =
callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
StringRef S = R"cpp(
void fcntl(int fd, int cmd, ...) {}
template <typename Func>
void f(Func F) {
int y = 42;
F(y, 1, 3);
}
void g() { f(fcntl); }
)cpp";
EXPECT_TRUE(matchAndVerifyResultTrue(
S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));
EXPECT_TRUE(matchAndVerifyResultTrue(
S, CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));
}
TEST(QualType, hasCanonicalType) { TEST(QualType, hasCanonicalType) {
EXPECT_TRUE(notMatches("typedef int &int_ref;" EXPECT_TRUE(notMatches("typedef int &int_ref;"
"int a;" "int a;"