clang-tools  14.0.0git
StringLiteralWithEmbeddedNulCheck.cpp
Go to the documentation of this file.
1 //===--- StringLiteralWithEmbeddedNulCheck.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 
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 
13 using namespace clang::ast_matchers;
14 
15 namespace clang {
16 namespace tidy {
17 namespace bugprone {
18 
19 namespace {
20 AST_MATCHER(StringLiteral, containsNul) {
21  for (size_t I = 0; I < Node.getLength(); ++I)
22  if (Node.getCodeUnit(I) == '\0')
23  return true;
24  return false;
25 }
26 } // namespace
27 
28 void StringLiteralWithEmbeddedNulCheck::registerMatchers(MatchFinder *Finder) {
29  // Match a string that contains embedded NUL character. Extra-checks are
30  // applied in |check| to find incorrectly escaped characters.
31  Finder->addMatcher(stringLiteral(containsNul()).bind("strlit"), this);
32 
33  // The remaining checks only apply to C++.
34  if (!getLangOpts().CPlusPlus)
35  return;
36 
37  const auto StrLitWithNul =
38  ignoringParenImpCasts(stringLiteral(containsNul()).bind("truncated"));
39 
40  // Match string constructor.
41  const auto StringConstructorExpr = expr(anyOf(
42  cxxConstructExpr(argumentCountIs(1),
43  hasDeclaration(cxxMethodDecl(hasName("basic_string")))),
44  // If present, the second argument is the alloc object which must not
45  // be present explicitly.
46  cxxConstructExpr(argumentCountIs(2),
47  hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
48  hasArgument(1, cxxDefaultArgExpr()))));
49 
50  // Detect passing a suspicious string literal to a string constructor.
51  // example: std::string str = "abc\0def";
52  Finder->addMatcher(traverse(TK_AsIs,
53  cxxConstructExpr(StringConstructorExpr, hasArgument(0, StrLitWithNul))),
54  this);
55 
56  // Detect passing a suspicious string literal through an overloaded operator.
57  Finder->addMatcher(cxxOperatorCallExpr(hasAnyArgument(StrLitWithNul)), this);
58 }
59 
61  const MatchFinder::MatchResult &Result) {
62  if (const auto *SL = Result.Nodes.getNodeAs<StringLiteral>("strlit")) {
63  for (size_t Offset = 0, Length = SL->getLength(); Offset < Length;
64  ++Offset) {
65  // Find a sequence of character like "\0x12".
66  if (Offset + 3 < Length && SL->getCodeUnit(Offset) == '\0' &&
67  SL->getCodeUnit(Offset + 1) == 'x' &&
68  isDigit(SL->getCodeUnit(Offset + 2)) &&
69  isDigit(SL->getCodeUnit(Offset + 3))) {
70  diag(SL->getBeginLoc(), "suspicious embedded NUL character");
71  return;
72  }
73  }
74  }
75 
76  if (const auto *SL = Result.Nodes.getNodeAs<StringLiteral>("truncated")) {
77  diag(SL->getBeginLoc(),
78  "truncated string literal with embedded NUL character");
79  }
80 }
81 
82 } // namespace bugprone
83 } // namespace tidy
84 } // namespace clang
StringLiteralWithEmbeddedNulCheck.h
Length
unsigned Length
Definition: SourceCodeTests.cpp:97
clang::ast_matchers
Definition: AbseilMatcher.h:14
Offset
size_t Offset
Definition: CodeComplete.cpp:1173
clang::ast_matchers::AST_MATCHER
AST_MATCHER(Expr, isMacroID)
Definition: PreferIsaOrDynCastInConditionalsCheck.cpp:19
clang::clangd::check
bool check(llvm::StringRef File, llvm::function_ref< bool(const Position &)> ShouldCheckLine, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, bool EnableCodeCompletion)
Definition: Check.cpp:259
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27