clang-tools  7.0.0
StringLiteralWithEmbeddedNulCheck.cpp
Go to the documentation of this file.
1 //===--- StringLiteralWithEmbeddedNulCheck.cpp - clang-tidy----------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace bugprone {
19 
20 namespace {
21 AST_MATCHER(StringLiteral, containsNul) {
22  for (size_t i = 0; i < Node.getLength(); ++i)
23  if (Node.getCodeUnit(i) == '\0')
24  return true;
25  return false;
26 }
27 } // namespace
28 
29 void StringLiteralWithEmbeddedNulCheck::registerMatchers(MatchFinder *Finder) {
30  // Match a string that contains embedded NUL character. Extra-checks are
31  // applied in |check| to find incorectly escaped characters.
32  Finder->addMatcher(stringLiteral(containsNul()).bind("strlit"), this);
33 
34  // The remaining checks only apply to C++.
35  if (!getLangOpts().CPlusPlus)
36  return;
37 
38  const auto StrLitWithNul =
39  ignoringParenImpCasts(stringLiteral(containsNul()).bind("truncated"));
40 
41  // Match string constructor.
42  const auto StringConstructorExpr = expr(anyOf(
43  cxxConstructExpr(argumentCountIs(1),
44  hasDeclaration(cxxMethodDecl(hasName("basic_string")))),
45  // If present, the second argument is the alloc object which must not
46  // be present explicitly.
47  cxxConstructExpr(argumentCountIs(2),
48  hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
49  hasArgument(1, cxxDefaultArgExpr()))));
50 
51  // Detect passing a suspicious string literal to a string constructor.
52  // example: std::string str = "abc\0def";
53  Finder->addMatcher(
54  cxxConstructExpr(StringConstructorExpr, hasArgument(0, StrLitWithNul)),
55  this);
56 
57  // Detect passing a suspicious string literal through an overloaded operator.
58  Finder->addMatcher(cxxOperatorCallExpr(hasAnyArgument(StrLitWithNul)), this);
59 }
60 
61 void StringLiteralWithEmbeddedNulCheck::check(
62  const MatchFinder::MatchResult &Result) {
63  if (const auto *SL = Result.Nodes.getNodeAs<StringLiteral>("strlit")) {
64  for (size_t Offset = 0, Length = SL->getLength(); Offset < Length;
65  ++Offset) {
66  // Find a sequence of character like "\0x12".
67  if (Offset + 3 < Length && SL->getCodeUnit(Offset) == '\0' &&
68  SL->getCodeUnit(Offset + 1) == 'x' &&
69  isDigit(SL->getCodeUnit(Offset + 2)) &&
70  isDigit(SL->getCodeUnit(Offset + 3))) {
71  diag(SL->getLocStart(), "suspicious embedded NUL character");
72  return;
73  }
74  }
75  }
76 
77  if (const auto *SL = Result.Nodes.getNodeAs<StringLiteral>("truncated")) {
78  diag(SL->getLocStart(),
79  "truncated string literal with embedded NUL character");
80  }
81 }
82 
83 } // namespace bugprone
84 } // namespace tidy
85 } // namespace clang
AST_MATCHER(BinaryOperator, isAssignmentOperator)
Definition: Matchers.h:20
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//