]> source.dussan.org Git - rspamd.git/commitdiff
More primitive types parsers
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 11 Nov 2015 14:05:48 +0000 (14:05 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 11 Nov 2015 14:05:48 +0000 (14:05 +0000)
clang-plugin/printf_check.cc

index cd9aa1de7180565de7bb0a676d32f5d22d2eb4c1..a6918e4255d144553aab79c4d03b0ab76e869708 100644 (file)
@@ -41,6 +41,16 @@ namespace rspamd {
                        struct PrintfArgChecker *ctx);
        static bool int_arg_handler (const Expr *arg,
                        struct PrintfArgChecker *ctx);
+       static bool long_arg_handler (const Expr *arg,
+                       struct PrintfArgChecker *ctx);
+       static bool size_arg_handler (const Expr *arg,
+                       struct PrintfArgChecker *ctx);
+       static bool char_arg_handler (const Expr *arg,
+                       struct PrintfArgChecker *ctx);
+       static bool double_arg_handler (const Expr *arg,
+                       struct PrintfArgChecker *ctx);
+       static bool long_double_arg_handler (const Expr *arg,
+                       struct PrintfArgChecker *ctx);
 
        using arg_parser_t = bool (*) (const Expr *, struct PrintfArgChecker *);
 
@@ -58,10 +68,16 @@ namespace rspamd {
        public:
                int width;
                int precision;
+               bool is_unsigned;
                ASTContext *past;
 
                PrintfArgChecker (arg_parser_t _p, ASTContext *_ast) :
-                               parser(_p), past(_ast) {}
+                               parser(_p), past(_ast)
+               {
+                       width = 0;
+                       precision = 0;
+                       is_unsigned = false;
+               }
                virtual ~PrintfArgChecker () {}
 
                bool operator () (const Expr *e)
@@ -85,6 +101,23 @@ namespace rspamd {
                        case 'd':
                                return llvm::make_unique<PrintfArgChecker>(int_arg_handler,
                                                this->pcontext);
+                       case 'z':
+                               return llvm::make_unique<PrintfArgChecker> (size_arg_handler,
+                                               this->pcontext);
+                       case 'l':
+                               return llvm::make_unique<PrintfArgChecker> (long_arg_handler,
+                                               this->pcontext);
+                       case 'f':
+                       case 'g':
+                               return llvm::make_unique<PrintfArgChecker> (double_arg_handler,
+                                               this->pcontext);
+                       case 'F':
+                       case 'G':
+                               return llvm::make_unique<PrintfArgChecker> (long_double_arg_handler,
+                                               this->pcontext);
+                       case 'c':
+                               return llvm::make_unique<PrintfArgChecker> (char_arg_handler,
+                                               this->pcontext);
                        default:
                                llvm::errs () << "unknown parser flag: " << type << "\n";
                                break;
@@ -366,4 +399,183 @@ namespace rspamd {
 
                return true;
        }
+
+       static bool
+       long_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx)
+       {
+               auto type = arg->getType ().split ().Ty;
+
+               auto desugared_type = type->getUnqualifiedDesugaredType ();
+
+               if (!desugared_type->isIntegerType ()) {
+                       print_error (
+                                       std::string ("bad integer argument for %l arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+               else if (!desugared_type->isBuiltinType ()) {
+                       print_error (
+                                       std::string ("bad integer argument for %l arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+
+               auto builtin_type = dyn_cast<BuiltinType> (desugared_type);
+               auto kind = builtin_type->getKind ();
+
+               if (kind != BuiltinType::Kind::ULong &&
+                               kind != BuiltinType::Kind::Long) {
+                       print_error (
+                                       std::string ("bad integer argument for %l arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+
+               return true;
+       }
+
+       static bool
+       char_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx)
+       {
+               auto type = arg->getType ().split ().Ty;
+
+               auto desugared_type = type->getUnqualifiedDesugaredType ();
+
+               if (!desugared_type->isCharType ()) {
+                       print_error (
+                                       std::string ("bad char argument for %c arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+               else if (!desugared_type->isBuiltinType ()) {
+                       print_error (
+                                       std::string ("bad char argument for %c arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+
+               auto builtin_type = dyn_cast<BuiltinType> (desugared_type);
+               auto kind = builtin_type->getKind ();
+
+               if (kind != BuiltinType::Kind::UChar &&
+                               kind != BuiltinType::Kind::SChar) {
+                       print_error (
+                                       std::string ("bad char argument for %c arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+
+               return true;
+       }
+
+       static bool
+       size_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx)
+       {
+               auto type = arg->getType ().split ().Ty;
+
+               auto desugared_type = type->getUnqualifiedDesugaredType ();
+
+               if (!desugared_type->isIntegerType ()) {
+                       print_error (
+                                       std::string ("bad integer argument for %z arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+               else if (!desugared_type->isBuiltinType ()) {
+                       print_error (
+                                       std::string ("bad integer argument for %z arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+
+               auto builtin_type = dyn_cast<BuiltinType> (desugared_type);
+               auto kind = builtin_type->getKind ();
+
+               if (sizeof (size_t) == sizeof (long)) {
+                       if (kind != BuiltinType::Kind::ULong &&
+                                       kind != BuiltinType::Kind::Long) {
+                               print_error (
+                                               std::string ("bad integer argument for %z arg: ") +
+                                                               arg->getType ().getAsString (), arg, ctx->past);
+                               return false;
+                       }
+               }
+               else if (sizeof (size_t) == sizeof (int)) {
+                       if (kind != BuiltinType::Kind::UInt &&
+                                       kind != BuiltinType::Kind::Int) {
+                               print_error (
+                                               std::string ("bad integer argument for %z arg: ") +
+                                                               arg->getType ().getAsString (), arg, ctx->past);
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       static bool
+       double_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx)
+       {
+               auto type = arg->getType ().split ().Ty;
+
+               auto desugared_type = type->getUnqualifiedDesugaredType ();
+
+               if (!desugared_type->isRealFloatingType ()) {
+                       print_error (
+                                       std::string ("bad double argument for %f or %g arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+               else if (!desugared_type->isBuiltinType ()) {
+                       print_error (
+                                       std::string ("bad double argument for %f or %g arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+
+               auto builtin_type = dyn_cast<BuiltinType> (desugared_type);
+               auto kind = builtin_type->getKind ();
+
+               if (kind != BuiltinType::Kind::Double) {
+                       print_error (
+                                       std::string ("bad double argument for %f or %g arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+
+               return true;
+       }
+
+       static bool
+       long_double_arg_handler (const Expr *arg, struct PrintfArgChecker *ctx)
+       {
+               auto type = arg->getType ().split ().Ty;
+
+               auto desugared_type = type->getUnqualifiedDesugaredType ();
+
+               if (!desugared_type->isRealFloatingType ()) {
+                       print_error (
+                                       std::string ("bad long double argument for %F or %G arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+               else if (!desugared_type->isBuiltinType ()) {
+                       print_error (
+                                       std::string ("bad long double argument for %F or %G arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+
+               auto builtin_type = dyn_cast<BuiltinType> (desugared_type);
+               auto kind = builtin_type->getKind ();
+
+               if (kind != BuiltinType::Kind::LongDouble) {
+                       print_error (
+                                       std::string ("bad long double argument for %F or %G arg: ") +
+                                                       arg->getType ().getAsString (), arg, ctx->past);
+                       return false;
+               }
+
+               return true;
+       }
 };