]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4222: Validating number parameter in a string form.
authorOleksii. Shumeiko -X (oshumeik - SOFTSERVE INC at Cisco) <oshumeik@cisco.com>
Wed, 28 Feb 2024 19:34:24 +0000 (19:34 +0000)
committerOleksii. Shumeiko -X (oshumeik - SOFTSERVE INC at Cisco) <oshumeik@cisco.com>
Wed, 28 Feb 2024 19:34:24 +0000 (19:34 +0000)
Merge in SNORT/snort3 from ~OSHUMEIK/snort3:cofig_parser_int_str to master

Squashed commit of the following:

commit ce64987a1dc2068944d7ebc52b685cf9909d8cb3
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date:   Wed Feb 28 16:11:02 2024 +0200

    main: update limits help

commit 3ed986bdca58218ea999d2cc46054f1f5556c698
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date:   Fri Feb 23 14:45:11 2024 +0200

    framework: validate parameter of number type in a string form

    Make string format strict. A few unit tests added.

src/framework/parameter.cc
src/framework/parameter.h
src/main/help.cc

index 28cdd17055c4a6fc41d871e9d01100841b7d2dae..07606cb30b0ea76d86cd3a5dcc131d394764a9ea 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <iomanip>
 #include <sstream>
+#include <type_traits>
 #include <vector>
 
 #include "utils/dnet_header.h"
@@ -86,62 +87,80 @@ static size_t split(const string& s, vector<string>& strs)
     return strs.size();
 }
 
-int64_t Parameter::get_int(const char* r)
+template <bool RV, typename T>
+static bool str2num(const char* r, T& t)
 {
-    if ( *r == 'm' )
-    {
-        if ( !strncmp(r, "maxSZ", 5) )
-            r = (sizeof(size_t) == 4) ? "max32" : "max53";
+    const int n = 5;
 
-        if ( !strncmp(r, "max31", 5) )
-            return 2147483647;
+    if ( *r != 'm' )
+        return false;
 
-        if ( !strncmp(r, "max32", 5) )
-            return 4294967295;
+    if ( !strncmp(r, "maxSZ", n) )
+        r = (sizeof(size_t) == 4) ? "max32" : "max53";
 
-        // Lua represents numbers in a 64-bit double. The max representable value is 9007199254740992
-        // and the min is -9007199254740992
-        if ( !strncmp(r, "max53", 5) )
-            return 9007199254740992;
+    bool res = true;
 
-        if ( !strncmp(r, "max63", 5) )
-            return 9223372036854775807;
+    if ( !strncmp(r, "max31", n) )
+        t = 2147483647;
 
-        if ( !strncmp(r, "max64", 5) )
-            return -1;
-    }
+    else if ( !strncmp(r, "max32", n) )
+        t = 4294967295;
+
+    // Lua represents numbers in a 64-bit double. The max representable value is 9007199254740992
+    // and the min is -9007199254740992
+    else if ( !strncmp(r, "max53", n) )
+        t = 9007199254740992;
+
+    else if ( !strncmp(r, "max63", n) )
+        t = 9223372036854775807;
+
+    else if ( !strncmp(r, "max64", n) )
+        t = std::is_same_v<T, int64_t> ? -1 : 18446744073709551615ULL;
+
+    else
+        res = false;
+
+    return res and (r[n] == '\0' or (RV and r[n] == ':'));
+}
+
+int64_t Parameter::get_int(const char* r)
+{
     char* end = nullptr;
     int64_t i = (int64_t)strtoll(r, &end, 0);
-    assert(!*end or *end == ':');
+
+    if (!str2num<true>(r, i))
+        assert(!*end or *end == ':');
 
     return i;
 }
 
 uint64_t Parameter::get_uint(const char* r)
 {
-    if ( *r == 'm' )
-    {
-        if ( !strncmp(r, "maxSZ", 5) )
-            r = (sizeof(size_t) == 4) ? "max32" : "max53";
+    char* end = nullptr;
+    uint64_t i = (uint64_t)strtoull(r, &end, 0);
 
-        if ( !strncmp(r, "max31", 5) )
-            return 2147483647;
+    if (!str2num<true>(r, i))
+        assert(!*end or *end == ':');
 
-        if ( !strncmp(r, "max32", 5) )
-            return 4294967295;
+    return i;
+}
 
-        if ( !strncmp(r, "max53", 5) )
-            return 9007199254740992;
+int64_t Parameter::get_int(const char* r, bool& is_correct)
+{
+    char* end = nullptr;
+    int64_t i = (int64_t)strtoll(r, &end, 0);
 
-        if ( !strncmp(r, "max63", 5) )
-            return 9223372036854775807;
+    is_correct = str2num<false>(r, i) or !*end;
 
-        if ( !strncmp(r, "max64", 5) )
-            return 18446744073709551615ULL;
-    }
+    return i;
+}
+
+uint64_t Parameter::get_uint(const char* r, bool& is_correct)
+{
     char* end = nullptr;
     uint64_t i = (uint64_t)strtoull(r, &end, 0);
-    assert(!*end or *end == ':');
+
+    is_correct = str2num<false>(r, i) or !*end;
 
     return i;
 }
@@ -159,44 +178,44 @@ static bool valid_bool(const Value& v, const char*)
 static bool valid_int(Value& v, const char* r)
 {
     bool signed_values;
+    bool is_correct = true;
+    uint64_t num;
+
     switch (v.get_type())
     {
-        case Value::VT_STR:
-            {
-                const char* str = v.get_string();
-                if (!str[0])
-                    return false;
-                signed_values = ('-' == str[0]);
-                if (!r || !r[0])
-                {
-                    if (signed_values)
-                        v.set((int64_t)strtoll(str, nullptr, 0));
-                    else
-                        v.set((uint64_t)strtoull(str, nullptr, 0));
-                    return true;
-                }
-            }
-            break;
-
-        case Value::VT_REAL:
-            {
-                double d = v.get_real();
-                signed_values = (0.0 > d);
-                if (!r || !r[0])
-                {
-                    if (signed_values)
-                        v.set((int64_t)d);
-                    else
-                        v.set((uint64_t)d);
-                    return true;
-                }
-            }
-            break;
-
-        default:
+    case Value::VT_STR:
+    {
+        const char* str = v.get_string();
+        const char f = str[0];
+
+        if (f == '\0' or isspace(f))
             return false;
+
+        signed_values = ('-' == f);
+        num = signed_values ? Parameter::get_int(str, is_correct) : Parameter::get_uint(str, is_correct);
+        break;
     }
 
+    case Value::VT_REAL:
+    {
+        double d = v.get_real();
+        signed_values = (0.0 > d);
+        num = (uint64_t)d;
+        break;
+    }
+
+    default:
+        return false;
+    }
+
+    if (is_correct)
+        signed_values ? v.set((int64_t)num) : v.set((uint64_t)num);
+    else
+        return false;
+
+    if (!r || !r[0])
+        return true;
+
     // require no leading or trailing whitespace
     // and either # | #: | :# | #:#
     // where # is a valid pos or neg dec, hex, or octal number
@@ -212,12 +231,8 @@ static bool valid_int(Value& v, const char* r)
 
     if (signed_values)
     {
-        int64_t d;
-        if (Value::VT_STR == v.get_type())
-            d = (int64_t)Parameter::get_int(v.get_string());
-        else
-            d = (int64_t)v.get_real();
-        v.set(d);
+        int64_t d = (int64_t)num;
+
         if (':' != *r)
         {
             int64_t low = Parameter::get_int(r);
@@ -235,12 +250,8 @@ static bool valid_int(Value& v, const char* r)
     }
     else
     {
-        uint64_t d;
-        if (Value::VT_STR == v.get_type())
-            d = Parameter::get_uint(v.get_string());
-        else
-            d = (uint64_t)v.get_real();
-        v.set(d);
+        uint64_t d = (uint64_t)num;
+
         if (':' != *r)
         {
             uint64_t low = Parameter::get_uint(r);
@@ -256,6 +267,7 @@ static bool valid_int(Value& v, const char* r)
                 return false;
         }
     }
+
     return true;
 }
 
@@ -702,6 +714,8 @@ num_tests[] =
     { false, valid_int, 1, "0" },
     { true, valid_int, 1, "0:" },
     { false, valid_int, 1, ":0" },
+    { true, valid_int, -1, "-1" },
+    { false, valid_int, 2, "-1" },
 
     { false, valid_int, 1.5, ":0" },
 
@@ -788,6 +802,44 @@ str_num_tests[] =
     { false, valid_int, "-52", ":-53" },
     { false, valid_int, "2", ":-53" },
 
+    { false, valid_int, "", "" },
+    { false, valid_int, "foo", "" },
+    { false, valid_int, "1a", "" },
+    { false, valid_int, "a1", "" },
+    { false, valid_int, " 1", "" },
+    { false, valid_int, "1 ", "" },
+    { false, valid_int, "\t\t2", "" },
+    { false, valid_int, "2\t\t", "" },
+    { false, valid_int, " -3", "" },
+    { false, valid_int, "-3 ", "" },
+    { false, valid_int, "4 5", "" },
+    { true, valid_int, "+10", "" },
+    { false, valid_int, "", "0:1" },
+    { false, valid_int, "foo", "0:1" },
+    { false, valid_int, "1a", "0:1" },
+    { false, valid_int, "a1", "0:1" },
+    { false, valid_int, " 1", "0:1" },
+    { false, valid_int, "1 ", "0:1" },
+    { false, valid_int, "\t\t2", "2:3" },
+    { false, valid_int, "2\t\t", "2:3" },
+    { false, valid_int, " -3", "-5:5" },
+    { false, valid_int, "-3 ", "-5:5" },
+    { false, valid_int, "4 5", "-5:5" },
+    { true, valid_int, "+10", "0:20" },
+
+    { true, valid_int, "max31", "" },
+    { true, valid_int, "max32", "" },
+    { true, valid_int, "max53", "" },
+    { true, valid_int, "max63", "" },
+    { true, valid_int, "max64", "" },
+    { true, valid_int, "max31", "max31" },
+    { false, valid_int, "max32", "max31" },
+
+    { false, valid_int, " max32", "" },
+    { false, valid_int, "max32 ", "" },
+    { false, valid_int, "maxN", "" },
+    { false, valid_int, "max31:max32", "" },
+
     { true, valid_real, "0.0", "0.0" },
     { true, valid_real, "0.0", ":0" },
 
index 3c57ca89652398659d776b2e7697810063b73f86..0cd40eba9f41de5c13aea0091014d633f9375353 100644 (file)
@@ -100,8 +100,11 @@ struct SO_PUBLIC Parameter
 
     // convert string to long long (including 'maxN' literals)
     static int64_t get_int(const char*);
+    static int64_t get_int(const char*, bool&);
+
     // convert string to unsigned long long (including 'maxN' literals)
     static uint64_t get_uint(const char*);
+    static uint64_t get_uint(const char*, bool&);
 };
 }
 #endif
index bd43ba136eb28e76132b08244315e53c7b7ea09b..fc0e4e9afd17946e041903638940298ab76e9c78 100644 (file)
@@ -256,6 +256,8 @@ void config_markup(SnortConfig*, const char*)
     fprintf(stdout, "max31 = 2147483647\n");
     fprintf(stdout, "max32 = 4294967295\n");
     fprintf(stdout, "max53 = 9007199254740992\n");
+    fprintf(stdout, "max63 = 9223372036854775807\n");
+    fprintf(stdout, "max64 = 18446744073709551615\n");
     fprintf(stdout, "maxSZ = %lu\n", (sizeof(size_t) == 4) ? 4294967295LU : 9007199254740992LU);
     exit(0);
 }