diff options
Diffstat (limited to 'clang-plugin')
-rw-r--r-- | clang-plugin/printf_check.cc | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/clang-plugin/printf_check.cc b/clang-plugin/printf_check.cc index 37e8dc399..7f20bdaac 100644 --- a/clang-plugin/printf_check.cc +++ b/clang-plugin/printf_check.cc @@ -22,6 +22,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <sys/types.h> #include "printf_check.h" #include "clang/AST/AST.h" #include "clang/AST/Expr.h" @@ -31,6 +32,9 @@ #include <vector> #include <sstream> #include <ctype.h> +#include <signal.h> +#include <assert.h> +#include <cstdint> using namespace clang; @@ -51,6 +55,12 @@ namespace rspamd { struct PrintfArgChecker *ctx); static bool long_double_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx); + static bool pointer_arg_handler (const Expr *arg, + struct PrintfArgChecker *ctx); + static bool pid_arg_handler (const Expr *arg, + struct PrintfArgChecker *ctx); + static bool int64_arg_handler (const Expr *arg, + struct PrintfArgChecker *ctx); using arg_parser_t = bool (*) (const Expr *, struct PrintfArgChecker *); @@ -118,6 +128,15 @@ namespace rspamd { case 'c': return llvm::make_unique<PrintfArgChecker> (char_arg_handler, this->pcontext); + case 'p': + return llvm::make_unique<PrintfArgChecker> (pointer_arg_handler, + this->pcontext); + case 'P': + return llvm::make_unique<PrintfArgChecker> (pid_arg_handler, + this->pcontext); + case 'L': + return llvm::make_unique<PrintfArgChecker> (int64_arg_handler, + this->pcontext); default: llvm::errs () << "unknown parser flag: " << type << "\n"; break; @@ -455,6 +474,9 @@ namespace rspamd { BuiltinType::Kind::Int}, "%z"); } + else { + assert (0); + } return true; } @@ -476,4 +498,64 @@ namespace rspamd { {BuiltinType::Kind::LongDouble}, "%F or %G"); } + static bool + pid_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx) + { + if (sizeof (pid_t) == sizeof (long)) { + return check_builtin_type (arg, + ctx, + {BuiltinType::Kind::ULong, + BuiltinType::Kind::Long}, + "%P"); + } + else if (sizeof (pid_t) == sizeof (int)) { + return check_builtin_type (arg, + ctx, + {BuiltinType::Kind::UInt, + BuiltinType::Kind::Int}, + "%P"); + } + else { + assert (0); + } + } + + static bool + pointer_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx) + { + auto type = arg->getType ().split ().Ty; + + if (!type->isPointerType ()) { + print_error ( + std::string ("bad pointer argument for %p: ") + + arg->getType ().getAsString (), arg, ctx->past); + return false; + } + + return true; + } + + static bool + int64_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx) + { + if (sizeof (int64_t) == sizeof (long long)) { + return check_builtin_type (arg, + ctx, + {BuiltinType::Kind::ULongLong, + BuiltinType::Kind::LongLong}, + "%L"); + } + else if (sizeof (int64_t) == sizeof (long)) { + return check_builtin_type (arg, + ctx, + {BuiltinType::Kind::ULong, + BuiltinType::Kind::Long}, + "%z"); + } + else { + assert (0); + } + + return true; + } }; |