From 432c149841757951d781307de88b31d08d705109 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 11 Nov 2015 16:18:22 +0000 Subject: [PATCH] Break compilation on format errors. --- clang-plugin/plugin.cc | 2 +- clang-plugin/printf_check.cc | 85 +++++++++++++++++++++--------------- clang-plugin/printf_check.h | 3 +- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/clang-plugin/plugin.cc b/clang-plugin/plugin.cc index 324e5169b..5d4dfc15f 100644 --- a/clang-plugin/plugin.cc +++ b/clang-plugin/plugin.cc @@ -48,7 +48,7 @@ namespace rspamd { void HandleTranslationUnit (ASTContext &context) override { - rspamd::PrintfCheckVisitor v(&context); + rspamd::PrintfCheckVisitor v(&context, Instance); v.TraverseDecl (context.getTranslationUnitDecl ()); } }; diff --git a/clang-plugin/printf_check.cc b/clang-plugin/printf_check.cc index c331942d9..76c1631bb 100644 --- a/clang-plugin/printf_check.cc +++ b/clang-plugin/printf_check.cc @@ -86,11 +86,14 @@ namespace rspamd { using arg_parser_t = bool (*) (const Expr *, struct PrintfArgChecker *); static void - print_error (const std::string &err, const Expr *e, const ASTContext *ast) + print_error (const std::string &err, const Expr *e, const ASTContext *ast, + CompilerInstance *ci) { - auto const &sm = ast->getSourceManager (); auto loc = e->getExprLoc (); - llvm::errs () << err << " at " << loc.printToString (sm) << "\n"; + auto &diag = ci->getDiagnostics (); + auto id = diag.getCustomDiagID (DiagnosticsEngine::Error, + "format query error: %0"); + diag.Report (loc, id) << err; } struct PrintfArgChecker { @@ -101,9 +104,10 @@ namespace rspamd { int precision; bool is_unsigned; ASTContext *past; + CompilerInstance *pci; - PrintfArgChecker (arg_parser_t _p, ASTContext *_ast) : - parser (_p), past (_ast) + PrintfArgChecker (arg_parser_t _p, ASTContext *_ast, CompilerInstance *_ci) : + parser (_p), past (_ast), pci(_ci) { width = 0; precision = 0; @@ -123,6 +127,7 @@ namespace rspamd { class PrintfCheckVisitor::impl { std::unordered_map printf_functions; ASTContext *pcontext; + CompilerInstance *ci; std::unique_ptr parseFlags (const std::string &flags) { @@ -131,49 +136,49 @@ namespace rspamd { switch (type) { case 's': return llvm::make_unique (cstring_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'd': return llvm::make_unique (int_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'z': return llvm::make_unique (size_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'l': return llvm::make_unique (long_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'f': case 'g': return llvm::make_unique (double_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'F': case 'G': return llvm::make_unique ( long_double_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'c': return llvm::make_unique (char_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'p': return llvm::make_unique (pointer_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'P': return llvm::make_unique (pid_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'L': return llvm::make_unique (int64_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'T': return llvm::make_unique (tok_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'V': return llvm::make_unique (fstring_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'v': return llvm::make_unique (gstring_arg_handler, - this->pcontext); + this->pcontext, this->ci); case 'e': return llvm::make_unique (gerr_arg_handler, - this->pcontext); + this->pcontext, this->ci); default: llvm::errs () << "unknown parser flag: " << type << "\n"; break; @@ -195,7 +200,7 @@ namespace rspamd { int width, precision; std::string flags; - auto res = std::make_shared < std::vector < PrintfArgChecker > > (); + auto res = std::make_shared > (); for (const auto c : query) { switch (state) { @@ -217,7 +222,8 @@ namespace rspamd { } else if (c == '*') { /* %*s - need integer argument */ - res->emplace_back (int_arg_handler, this->pcontext); + res->emplace_back (int_arg_handler, this->pcontext, + this->ci); state = read_arg; } else if (c == '%') { @@ -249,7 +255,8 @@ namespace rspamd { precision += c - '0'; } else if (c == '*') { - res->emplace_back (int_arg_handler, this->pcontext); + res->emplace_back (int_arg_handler, this->pcontext, + this->ci); state = read_arg; } else { @@ -305,7 +312,8 @@ namespace rspamd { } public: - impl (ASTContext *_ctx) : pcontext (_ctx) + impl (ASTContext *_ctx, clang::CompilerInstance &_ci) + : pcontext (_ctx), ci(&_ci) { /* name -> format string position */ printf_functions = { @@ -365,7 +373,7 @@ namespace rspamd { << ", got " << (E->getNumArgs () - (pos + 1)) << " args"; - print_error (err_buf.str (), E, this->pcontext); + print_error (err_buf.str (), E, this->pcontext, this->ci); return false; } @@ -387,8 +395,9 @@ namespace rspamd { } }; - PrintfCheckVisitor::PrintfCheckVisitor (ASTContext *ctx) : - pimpl{new impl (ctx)} + PrintfCheckVisitor::PrintfCheckVisitor (ASTContext *ctx, + clang::CompilerInstance &ci) : + pimpl{new impl (ctx, ci)} { } @@ -410,7 +419,8 @@ namespace rspamd { if (!type->isPointerType ()) { print_error ( std::string ("bad string argument for %s: ") + - arg->getType ().getAsString (), arg, ctx->past); + arg->getType ().getAsString (), + arg, ctx->past, ctx->pci); return false; } @@ -428,7 +438,8 @@ namespace rspamd { } print_error ( std::string ("bad string argument for %s: ") + - arg->getType ().getAsString (), arg, ctx->past); + arg->getType ().getAsString (), + arg, ctx->past, ctx->pci); return false; } } @@ -447,7 +458,8 @@ namespace rspamd { if (!desugared_type->isBuiltinType ()) { print_error ( std::string ("not a builtin type for ") + fmt + " arg: " + - arg->getType ().getAsString (), arg, ctx->past); + arg->getType ().getAsString (), + arg, ctx->past, ctx->pci); return false; } @@ -465,7 +477,8 @@ namespace rspamd { if (!found) { print_error ( std::string ("bad argument for ") + fmt + " arg: " + - arg->getType ().getAsString (), arg, ctx->past); + arg->getType ().getAsString (), + arg, ctx->past, ctx->pci); return false; } @@ -574,7 +587,8 @@ namespace rspamd { if (!type->isPointerType ()) { print_error ( std::string ("bad pointer argument for %p: ") + - arg->getType ().getAsString (), arg, ctx->past); + arg->getType ().getAsString (), + arg, ctx->past, ctx->pci); return false; } @@ -614,7 +628,8 @@ namespace rspamd { if (!type->isPointerType ()) { print_error ( std::string ("bad string argument for %s: ") + - arg->getType ().getAsString (), arg, ctx->past); + arg->getType ().getAsString (), + arg, ctx->past, ctx->pci); return false; } @@ -624,7 +639,8 @@ namespace rspamd { if (!desugared_type->isRecordType ()) { print_error ( std::string ("not a record type for ") + fmt + " arg: " + - arg->getType ().getAsString (), arg, ctx->past); + arg->getType ().getAsString (), + arg, ctx->past, ctx->pci); return false; } @@ -635,7 +651,8 @@ namespace rspamd { if (struct_def != sname) { print_error (std::string ("bad argument '") + struct_def + "' for " + fmt + " arg: " + - arg->getType ().getAsString (), arg, ctx->past); + arg->getType ().getAsString (), + arg, ctx->past, ctx->pci); return false; } diff --git a/clang-plugin/printf_check.h b/clang-plugin/printf_check.h index 13e1ca86c..8f9fa277a 100644 --- a/clang-plugin/printf_check.h +++ b/clang-plugin/printf_check.h @@ -28,6 +28,7 @@ #include #include "clang/AST/AST.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" #include "clang/AST/Expr.h" namespace rspamd { @@ -37,7 +38,7 @@ namespace rspamd { std::unique_ptr pimpl; public: - PrintfCheckVisitor (clang::ASTContext *ctx); + PrintfCheckVisitor (clang::ASTContext *ctx, clang::CompilerInstance &ci); virtual ~PrintfCheckVisitor (void); bool VisitCallExpr (clang::CallExpr *E); }; -- 2.39.5