1//===--- SuspiciousStringviewDataUsageCheck.cpp - clang-tidy --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "SuspiciousStringviewDataUsageCheck.h"
10#include "../utils/Matchers.h"
11#include "../utils/OptionsUtils.h"
12#include "clang/AST/ASTContext.h"
13#include "clang/ASTMatchers/ASTMatchFinder.h"
14
15using namespace clang::ast_matchers;
16
17namespace clang::tidy::bugprone {
18
19SuspiciousStringviewDataUsageCheck::SuspiciousStringviewDataUsageCheck(
20 StringRef Name, ClangTidyContext *Context)
21 : ClangTidyCheck(Name, Context),
22 StringViewTypes(utils::options::parseStringList(Option: Options.get(
23 LocalName: "StringViewTypes", Default: "::std::basic_string_view;::llvm::StringRef"))),
24 AllowedCallees(
25 utils::options::parseStringList(Option: Options.get(LocalName: "AllowedCallees", Default: ""))) {}
26
27void SuspiciousStringviewDataUsageCheck::storeOptions(
28 ClangTidyOptions::OptionMap &Opts) {
29 Options.store(Options&: Opts, LocalName: "StringViewTypes",
30 Value: utils::options::serializeStringList(Strings: StringViewTypes));
31 Options.store(Options&: Opts, LocalName: "AllowedCallees",
32 Value: utils::options::serializeStringList(Strings: AllowedCallees));
33}
34
35bool SuspiciousStringviewDataUsageCheck::isLanguageVersionSupported(
36 const LangOptions &LangOpts) const {
37 return LangOpts.CPlusPlus;
38}
39
40std::optional<TraversalKind>
41SuspiciousStringviewDataUsageCheck::getCheckTraversalKind() const {
42 return TK_AsIs;
43}
44
45void SuspiciousStringviewDataUsageCheck::registerMatchers(MatchFinder *Finder) {
46
47 auto AncestorCall = anyOf(
48 cxxConstructExpr(), callExpr(unless(cxxOperatorCallExpr())), lambdaExpr(),
49 initListExpr(
50 hasType(InnerMatcher: qualType(hasCanonicalType(InnerMatcher: hasDeclaration(InnerMatcher: recordDecl()))))));
51
52 auto DataMethod =
53 cxxMethodDecl(hasName(Name: "data"),
54 ofClass(InnerMatcher: matchers::matchesAnyListedName(NameList: StringViewTypes)));
55
56 auto SizeCall = cxxMemberCallExpr(
57 callee(InnerMatcher: cxxMethodDecl(hasAnyName("size", "length"))),
58 on(InnerMatcher: ignoringParenImpCasts(
59 InnerMatcher: matchers::isStatementIdenticalToBoundNode(ID: "self"))));
60
61 auto DescendantSizeCall = expr(hasDescendant(
62 expr(SizeCall, hasAncestor(expr(AncestorCall).bind(ID: "ancestor-size")),
63 hasAncestor(expr(equalsBoundNode(ID: "parent"),
64 equalsBoundNode(ID: "ancestor-size"))))));
65
66 Finder->addMatcher(
67 NodeMatch: cxxMemberCallExpr(
68 on(InnerMatcher: ignoringParenImpCasts(InnerMatcher: expr().bind(ID: "self"))), callee(InnerMatcher: DataMethod),
69 expr().bind(ID: "data-call"),
70 hasParent(expr(anyOf(
71 invocation(
72 expr().bind(ID: "parent"), unless(cxxOperatorCallExpr()),
73 hasAnyArgument(
74 InnerMatcher: ignoringParenImpCasts(InnerMatcher: equalsBoundNode(ID: "data-call"))),
75 unless(hasAnyArgument(InnerMatcher: ignoringParenImpCasts(InnerMatcher: SizeCall))),
76 unless(hasAnyArgument(InnerMatcher: DescendantSizeCall)),
77 hasDeclaration(InnerMatcher: namedDecl(
78 unless(matchers::matchesAnyListedName(NameList: AllowedCallees))))),
79 initListExpr(expr().bind(ID: "parent"),
80 hasType(InnerMatcher: qualType(hasCanonicalType(InnerMatcher: hasDeclaration(
81 InnerMatcher: recordDecl(unless(matchers::matchesAnyListedName(
82 NameList: AllowedCallees))))))),
83 unless(DescendantSizeCall)))))),
84 Action: this);
85}
86
87void SuspiciousStringviewDataUsageCheck::check(
88 const MatchFinder::MatchResult &Result) {
89 const auto *DataCallExpr =
90 Result.Nodes.getNodeAs<CXXMemberCallExpr>(ID: "data-call");
91 diag(Loc: DataCallExpr->getExprLoc(),
92 Description: "result of a `data()` call may not be null terminated, provide size "
93 "information to the callee to prevent potential issues")
94 << DataCallExpr->getCallee()->getSourceRange();
95}
96
97} // namespace clang::tidy::bugprone
98

source code of clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp