clang-tools 8.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
10 #include "StringLiteralWithEmbeddedNulCheck.h"
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->getBeginLoc(), "suspicious embedded NUL character");
72 return;
73 }
74 }
75 }
76
77 if (const auto *SL = Result.Nodes.getNodeAs<StringLiteral>("truncated")) {
78 diag(SL->getBeginLoc(),
79 "truncated string literal with embedded NUL character");
80 }
81 }
82
83 } // namespace bugprone
84 } // namespace tidy
85 } // namespace clang
clang::ast_matchers
Definition: AbseilMatcher.h:15
clang::tidy::matchers::AST_MATCHER
AST_MATCHER(BinaryOperator, isAssignmentOperator)
Definition: Matchers.h:20
Result
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Definition: ClangdServer.cpp:60
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ChangeNamespace.cpp:18
StringLiteralWithEmbeddedNulCheck.h