CStringSyntaxChecker.cpp revision 8fe83e1df954d72c0f4ffc15d20a5222ec151c21
146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//== CStringSyntaxChecker.cpp - CoreFoundation containers API *- C++ -*-==// 246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// 346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// The LLVM Compiler Infrastructure 446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// 546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// License. See LICENSE.TXT for details. 746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// 846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//===----------------------------------------------------------------------===// 946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// 1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// An AST checker that looks for common pitfalls when using C string APIs. 1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// - Identifies erroneous patterns in the last argument to strncat - the number 1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// of bytes to copy. 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//===----------------------------------------------------------------------===// 1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ClangSACheckers.h" 1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/Analysis/AnalysisContext.h" 1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/AST/Expr.h" 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/AST/OperationKinds.h" 1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/AST/StmtVisitor.h" 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/Basic/TargetInfo.h" 2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/Basic/TypeTraits.h" 2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "llvm/ADT/SmallString.h" 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "llvm/Support/raw_ostream.h" 2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using namespace clang; 3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using namespace ento; 3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace { 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class WalkAST: public StmtVisitor<WalkAST> { 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BugReporter &BR; 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) AnalysisDeclContext* AC; 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASTContext &ASTC; 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) /// Check if two expressions refer to the same declaration. 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) inline bool sameDecl(const Expr *A1, const Expr *A2) { 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const DeclRefExpr *D1 = dyn_cast<DeclRefExpr>(A1->IgnoreParenCasts())) 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const DeclRefExpr *D2 = dyn_cast<DeclRefExpr>(A2->IgnoreParenCasts())) 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return D1->getDecl() == D2->getDecl(); 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) /// Check if the expression E is a sizeof(WithArg). 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) inline bool isSizeof(const Expr *E, const Expr *WithArg) { 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (const UnaryExprOrTypeTraitExpr *UE = 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dyn_cast<UnaryExprOrTypeTraitExpr>(E)) 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (UE->getKind() == UETT_SizeOf) 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return sameDecl(UE->getArgumentExpr(), WithArg); 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) /// Check if the expression E is a strlen(WithArg). 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) inline bool isStrlen(const Expr *E, const Expr *WithArg) { 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const FunctionDecl *FD = CE->getDirectCallee(); 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!FD) 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return (CheckerContext::isCLibraryFunction(FD, "strlen", ASTC) 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) && sameDecl(CE->getArg(0), WithArg)); 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) /// Check if the expression is an integer literal with value 1. 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch inline bool isOne(const Expr *E) { 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E)) 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return (IL->getValue().isIntN(1)); 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) inline StringRef getPrintableName(const Expr *E) { 7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const DeclRefExpr *D = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts())) 7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return D->getDecl()->getName(); 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return StringRef(); 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) /// Identify erroneous patterns in the last argument to strncat - the number 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) /// of bytes to copy. 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool containsBadStrncatPattern(const CallExpr *CE); 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)public: 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WalkAST(BugReporter &br, AnalysisDeclContext* ac) : 8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BR(br), AC(ac), ASTC(AC->getASTContext()) { 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Statement visitor methods. 9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void VisitChildren(Stmt *S); 9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void VisitStmt(Stmt *S) { 9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VisitChildren(S); 9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void VisitCallExpr(CallExpr *CE); 9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} // end anonymous namespace 9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// The correct size argument should look like following: 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// strncat(dst, src, sizeof(dst) - strlen(dest) - 1); 10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// We look for the following anti-patterns: 10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// - strncat(dst, src, sizeof(dst) - strlen(dst)); 10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// - strncat(dst, src, sizeof(dst) - 1); 10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// - strncat(dst, src, sizeof(dst)); 10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool WalkAST::containsBadStrncatPattern(const CallExpr *CE) { 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Expr *DstArg = CE->getArg(0); 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Expr *SrcArg = CE->getArg(1); 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const Expr *LenArg = CE->getArg(2); 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Identify wrong size expressions, which are commonly used instead. 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (const BinaryOperator *BE = 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) dyn_cast<BinaryOperator>(LenArg->IgnoreParenCasts())) { 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // - sizeof(dst) - strlen(dst) 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (BE->getOpcode() == BO_Sub) { 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const Expr *L = BE->getLHS(); 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const Expr *R = BE->getRHS(); 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (isSizeof(L, DstArg) && isStrlen(R, DstArg)) 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // - sizeof(dst) - 1 12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (isSizeof(L, DstArg) && isOne(R->IgnoreParenCasts())) 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // - sizeof(dst) 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (isSizeof(LenArg, DstArg)) 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // - sizeof(src) 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (isSizeof(LenArg, SrcArg)) 13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WalkAST::VisitCallExpr(CallExpr *CE) { 13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const FunctionDecl *FD = CE->getDirectCallee(); 13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!FD) 13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (CheckerContext::isCLibraryFunction(FD, "strncat", ASTC)) { 14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (containsBadStrncatPattern(CE)) { 14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Expr *DstArg = CE->getArg(0); 14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Expr *LenArg = CE->getArg(2); 14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SourceRange R = LenArg->getSourceRange(); 14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PathDiagnosticLocation Loc = 14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PathDiagnosticLocation::createBegin(LenArg, BR.getSourceManager(), AC); 14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) StringRef DstName = getPrintableName(DstArg); 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) llvm::SmallString<256> S; 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) llvm::raw_svector_ostream os(S); 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) os << "Potential buffer overflow. "; 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!DstName.empty()) { 15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) os << "Replace with 'sizeof(" << DstName << ") " 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "- strlen(" << DstName <<") - 1'"; 15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) os << " or u"; 15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } else 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) os << "U"; 15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) os << "se a safer 'strlcat' API"; 15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BR.EmitBasicReport("Anti-pattern in the argument", "C String API", 16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) os.str(), Loc, &R, 1); 16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Recurse and check children. 16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VisitChildren(CE); 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void WalkAST::VisitChildren(Stmt *S) { 17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E; 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ++I) 17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (Stmt *child = *I) 17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Visit(child); 17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace { 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class CStringSyntaxChecker: public Checker<check::ASTCodeBody> { 17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)public: 17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr, 18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BugReporter &BR) const { 18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WalkAST walker(BR, Mgr.getAnalysisDeclContext(D)); 18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) walker.Visit(D->getBody()); 18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ento::registerCStringSyntaxChecker(CheckerManager &mgr) { 18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) mgr.registerChecker<CStringSyntaxChecker>(); 19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)