11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 20 void MisplacedOperatorInStrlenInAllocCheck::registerMatchers(
21 MatchFinder *Finder) {
22 const auto StrLenFunc = functionDecl(anyOf(
23 hasName(
"::strlen"), hasName(
"::std::strlen"), hasName(
"::strnlen"),
24 hasName(
"::std::strnlen"), hasName(
"::strnlen_s"),
25 hasName(
"::std::strnlen_s"), hasName(
"::wcslen"),
26 hasName(
"::std::wcslen"), hasName(
"::wcsnlen"), hasName(
"::std::wcsnlen"),
27 hasName(
"::wcsnlen_s"), hasName(
"std::wcsnlen_s")));
30 callExpr(callee(StrLenFunc),
31 hasAnyArgument(ignoringImpCasts(
32 binaryOperator(allOf(hasOperatorName(
"+"),
33 hasRHS(ignoringParenImpCasts(
34 integerLiteral(equals(1))))))
38 const auto BadArg = anyOf(
39 allOf(hasDescendant(BadUse),
40 unless(binaryOperator(allOf(
41 hasOperatorName(
"+"), hasLHS(BadUse),
42 hasRHS(ignoringParenImpCasts(integerLiteral(equals(1)))))))),
45 const auto Alloc0Func =
46 functionDecl(anyOf(hasName(
"::malloc"), hasName(
"std::malloc"),
47 hasName(
"::alloca"), hasName(
"std::alloca")));
48 const auto Alloc1Func =
49 functionDecl(anyOf(hasName(
"::calloc"), hasName(
"std::calloc"),
50 hasName(
"::realloc"), hasName(
"std::realloc")));
52 const auto Alloc0FuncPtr =
53 varDecl(hasType(isConstQualified()),
54 hasInitializer(ignoringParenImpCasts(
55 declRefExpr(hasDeclaration(Alloc0Func)))));
56 const auto Alloc1FuncPtr =
57 varDecl(hasType(isConstQualified()),
58 hasInitializer(ignoringParenImpCasts(
59 declRefExpr(hasDeclaration(Alloc1Func)))));
61 Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))),
62 hasArgument(0, BadArg))
65 Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))),
66 hasArgument(1, BadArg))
70 cxxNewExpr(isArray(), hasArraySize(BadArg)).bind(
"Alloc"),
this);
73 void MisplacedOperatorInStrlenInAllocCheck::check(
74 const MatchFinder::MatchResult &Result) {
75 const Expr *Alloc = Result.Nodes.getNodeAs<CallExpr>(
"Alloc");
77 Alloc = Result.Nodes.getNodeAs<CXXNewExpr>(
"Alloc");
78 assert(Alloc &&
"Matched node bound by 'Alloc' shoud be either 'CallExpr'" 81 const auto *StrLen = Result.Nodes.getNodeAs<CallExpr>(
"StrLen");
82 const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>(
"BinOp");
84 const StringRef StrLenText = Lexer::getSourceText(
85 CharSourceRange::getTokenRange(StrLen->getSourceRange()),
86 *Result.SourceManager, getLangOpts());
87 const StringRef Arg0Text = Lexer::getSourceText(
88 CharSourceRange::getTokenRange(StrLen->getArg(0)->getSourceRange()),
89 *Result.SourceManager, getLangOpts());
90 const StringRef StrLenBegin = StrLenText.substr(0, StrLenText.find(Arg0Text));
91 const StringRef StrLenEnd = StrLenText.substr(
92 StrLenText.find(Arg0Text) + Arg0Text.size(), StrLenText.size());
94 const StringRef LHSText = Lexer::getSourceText(
95 CharSourceRange::getTokenRange(BinOp->getLHS()->getSourceRange()),
96 *Result.SourceManager, getLangOpts());
97 const StringRef RHSText = Lexer::getSourceText(
98 CharSourceRange::getTokenRange(BinOp->getRHS()->getSourceRange()),
99 *Result.SourceManager, getLangOpts());
101 auto Hint = FixItHint::CreateReplacement(
102 StrLen->getSourceRange(),
103 (StrLenBegin + LHSText + StrLenEnd +
" + " + RHSText).str());
105 diag(Alloc->getLocStart(),
106 "addition operator is applied to the argument of %0 instead of its " 107 "result") << StrLen->getDirectCallee()->getName() << Hint;
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//