]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
Use separate module for printf checks.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 10 Nov 2015 23:55:24 +0000 (23:55 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 10 Nov 2015 23:55:24 +0000 (23:55 +0000)
clang-plugin/CMakeLists.txt
clang-plugin/plugin.cc
clang-plugin/printf_check.cc [new file with mode: 0644]
clang-plugin/printf_check.h [new file with mode: 0644]

index 02ffdc1739d8e743272e42bce48cb4cfc7a68daa..eae7642353a6bce13cad67d2b266afc752a7d1ec 100644 (file)
@@ -8,7 +8,7 @@ IF (ENABLE_CLANG_PLUGIN MATCHES "ON")
     ENABLE_LANGUAGE(CXX)
     FIND_PACKAGE(LLVM REQUIRED)
 
-    SET(CLANGPLUGINSRC plugin.cc)
+    SET(CLANGPLUGINSRC plugin.cc printf_check.cc)
 
     ADD_LIBRARY(rspamd-clang SHARED ${CLANGPLUGINSRC})
     SET_TARGET_PROPERTIES(rspamd-clang PROPERTIES
index 1d80ba23175cdb26722266b4dcf306d545910761..324e5169b4c79505e318791906d69b4f383b7d96 100644 (file)
 
 #include "clang/Frontend/FrontendPluginRegistry.h"
 #include "clang/AST/AST.h"
-#include "clang/AST/Expr.h"
 #include "clang/AST/ASTConsumer.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Sema/Sema.h"
 #include "llvm/Support/raw_ostream.h"
-#include <unordered_map>
+#include "printf_check.h"
+
 
 using namespace clang;
 
-namespace {
+namespace rspamd {
 
        class RspamdASTConsumer : public ASTConsumer {
                CompilerInstance &Instance;
@@ -49,71 +48,7 @@ namespace {
 
                void HandleTranslationUnit (ASTContext &context) override
                {
-                       struct Visitor : public RecursiveASTVisitor<Visitor> {
-                               std::unordered_map<std::string, int> printf_functions;
-                               ASTContext *pcontext;
-
-                               Visitor (void)
-                               {
-                                       /* name -> format string position */
-                                       printf_functions = {
-                                                       {"rspamd_printf", 0},
-                                                       {"rspamd_default_log_function", 4},
-                                                       {"rspamd_snprintf", 2},
-                                                       {"rspamd_fprintf", 1}
-                                       };
-                               };
-
-                               bool VisitCallExpr (CallExpr *E)
-                               {
-                                       auto callee = dyn_cast<NamedDecl> (E->getCalleeDecl ());
-                                       if (callee == NULL) {
-                                               llvm::errs () << "Bad callee\n";
-                                               return false;
-                                       }
-
-                                       auto fname = callee->getNameAsString ();
-
-                                       auto pos_it = printf_functions.find (fname);
-
-                                       if (pos_it != printf_functions.end ()) {
-                                               const auto args = E->getArgs ();
-                                               auto pos = pos_it->second;
-                                               auto query = args[pos];
-
-                                               if (!query->isEvaluatable(*pcontext)) {
-                                                       llvm::errs () << "Cannot evaluate query\n";
-                                                       return false;
-                                               }
-
-                                               clang::Expr::EvalResult r;
-
-                                               if (!query->EvaluateAsRValue (r, *pcontext)) {
-                                                       llvm::errs () << "Cannot evaluate query\n";
-                                                       return false;
-                                               }
-
-                                               auto qval = dyn_cast<StringLiteral> (
-                                                               r.Val.getLValueBase ().get<const Expr *> ());
-                                               if (qval) {
-                                                       llvm::errs () << "query string: "
-                                                                       << qval->getString () << "\n";
-                                               }
-
-                                               for (auto i = pos + 1; i < E->getNumArgs (); i ++) {
-                                                       auto arg = args[i];
-
-                                                       if (arg) {
-                                                               arg->dump ();
-                                                       }
-                                               }
-                                       }
-
-                                       return true;
-                               }
-
-                       } v;
-                       v.pcontext = &context;
+                       rspamd::PrintfCheckVisitor v(&context);
                        v.TraverseDecl (context.getTranslationUnitDecl ());
                }
        };
@@ -141,5 +76,5 @@ namespace {
 
 }
 
-static FrontendPluginRegistry::Add <RspamdASTAction>
+static FrontendPluginRegistry::Add <rspamd::RspamdASTAction>
                X ("rspamd-ast", "rspamd ast checker");
diff --git a/clang-plugin/printf_check.cc b/clang-plugin/printf_check.cc
new file mode 100644 (file)
index 0000000..4c0e8ed
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *      * Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ *      * Redistributions in binary form must reproduce the above copyright
+ *        notice, this list of conditions and the following disclaimer in the
+ *        documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "printf_check.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include <unordered_map>
+
+using namespace clang;
+
+namespace rspamd {
+       class PrintfCheckVisitor::impl {
+               std::unordered_map<std::string, int> printf_functions;
+               ASTContext *pcontext;
+
+       public:
+               impl (ASTContext *_ctx) : pcontext(_ctx)
+               {
+                       /* name -> format string position */
+                       printf_functions = {
+                                       {"rspamd_printf",               0},
+                                       {"rspamd_default_log_function", 4},
+                                       {"rspamd_snprintf",             2},
+                                       {"rspamd_fprintf",              1}
+                       };
+               };
+
+               bool VisitCallExpr (CallExpr *E)
+               {
+                       auto callee = dyn_cast<NamedDecl> (E->getCalleeDecl ());
+                       if (callee == NULL) {
+                               llvm::errs () << "Bad callee\n";
+                               return false;
+                       }
+
+                       auto fname = callee->getNameAsString ();
+
+                       auto pos_it = printf_functions.find (fname);
+
+                       if (pos_it != printf_functions.end ()) {
+                               const auto args = E->getArgs ();
+                               auto pos = pos_it->second;
+                               auto query = args[pos];
+
+                               if (!query->isEvaluatable (*pcontext)) {
+                                       llvm::errs () << "Cannot evaluate query\n";
+                                       return false;
+                               }
+
+                               clang::Expr::EvalResult r;
+
+                               if (!query->EvaluateAsRValue (r, *pcontext)) {
+                                       llvm::errs () << "Cannot evaluate query\n";
+                                       return false;
+                               }
+
+                               auto qval = dyn_cast<StringLiteral> (
+                                               r.Val.getLValueBase ().get<const Expr *> ());
+                               if (qval) {
+                                       llvm::errs () << "query string: "
+                                                       << qval->getString () << "\n";
+                               }
+
+                               for (auto i = pos + 1; i < E->getNumArgs (); i++) {
+                                       auto arg = args[i];
+
+                                       if (arg) {
+                                               auto type = arg->getType ().split ().Ty;
+                                               type->dump ();
+                                       }
+                               }
+                       }
+
+                       return true;
+               }
+       };
+
+       PrintfCheckVisitor::PrintfCheckVisitor (ASTContext *ctx) :
+               pimpl { new impl(ctx) }
+       {
+       }
+
+       PrintfCheckVisitor::~PrintfCheckVisitor ()
+       {
+       }
+
+       bool PrintfCheckVisitor::VisitCallExpr (clang::CallExpr *E)
+       {
+               return pimpl->VisitCallExpr (E);
+       }
+};
diff --git a/clang-plugin/printf_check.h b/clang-plugin/printf_check.h
new file mode 100644 (file)
index 0000000..13e1ca8
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *      * Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ *      * Redistributions in binary form must reproduce the above copyright
+ *        notice, this list of conditions and the following disclaimer in the
+ *        documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RSPAMD_PRINTF_CHECK_H
+#define RSPAMD_PRINTF_CHECK_H
+
+#include <memory>
+#include "clang/AST/AST.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Expr.h"
+
+namespace rspamd {
+
+       class PrintfCheckVisitor : public clang::RecursiveASTVisitor<PrintfCheckVisitor> {
+               class impl;
+               std::unique_ptr<impl> pimpl;
+
+       public:
+               PrintfCheckVisitor (clang::ASTContext *ctx);
+               virtual ~PrintfCheckVisitor (void);
+               bool VisitCallExpr (clang::CallExpr *E);
+       };
+
+}
+
+#endif