]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3370: JS stack limit.
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 12 Apr 2022 12:29:06 +0000 (12:29 +0000)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 12 Apr 2022 12:29:06 +0000 (12:29 +0000)
Merge in SNORT/snort3 from ~OSHUMEIK/snort3:js_regex_grp_limit to master

Squashed commit of the following:

commit 07c377d4a4c4e3aea177047747fbe61fcf1a4b27
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date:   Mon Apr 11 11:43:30 2022 +0300

    utils: limit JS regex stack size

    The 'http_inspect.js_norm_max_tmpl_nest' configuration option controls the limit.

src/utils/js_tokenizer.h
src/utils/js_tokenizer.l
src/utils/test/js_normalizer_test.cc

index 15f70c900204e5a0afc1e95c66b82153e61b6586..96e0d509af0f2bb1f362e79692c19baae1bc8eb5 100644 (file)
@@ -140,6 +140,9 @@ private:
         ALIAS_VALUE       // var a = eval
     };
 
+    template <class T>
+    using VStack = std::stack<T, std::vector<T>>;
+
 public:
     enum JSRet
     {
@@ -317,14 +320,14 @@ private:
     bool mixed_encoding_seen = false;
 
     uint8_t max_template_nesting;
-    std::stack<uint16_t, std::vector<uint16_t>> brace_depth;
+    VStack<uint16_t> brace_depth;
     JSToken token = UNDEFINED;
     ASIGroup previous_group = ASI_OTHER;
     JSIdentifierCtxBase& ident_ctx;
     size_t bytes_read;
     size_t tmp_bytes_read;
     bool ext_script;
-    std::stack<char> regex_stack;
+    VStack<char> regex_stack;
 
     struct
     {
index cdfde3cd003920de805422504701feddce60c730..24c5f78af68042e3f55604a51d16f3ddf9f21ef1 100644 (file)
@@ -1656,7 +1656,7 @@ void JSTokenizer::states_reset()
     if (tmp_buffer)
         switch_to_initial();
 
-    brace_depth = std::stack<uint16_t, std::vector<uint16_t>>();
+    brace_depth = VStack<uint16_t>();
     token = UNDEFINED;
     previous_group = ASI_OTHER;
 
@@ -2282,7 +2282,7 @@ JSTokenizer::JSRet JSTokenizer::literal_regex_start()
     yyless(1);
     BEGIN(regex);
     set_ident_norm(true);
-    regex_stack = std::stack<char>();
+    regex_stack = VStack<char>();
     return EOS;
 }
 
@@ -2303,6 +2303,9 @@ JSTokenizer::JSRet JSTokenizer::literal_regex_end()
 
 JSTokenizer::JSRet JSTokenizer::literal_regex_g_open()
 {
+    if (regex_stack.size() >= max_template_nesting)
+        return TEMPLATE_NESTING_OVERFLOW;
+
     regex_stack.push(yytext[0]);
     ECHO;
     return EOS;
index b516f9b27a9321282d0b661e2b41c736a3a92a22..36dffebc139a22b5a707e34a3193e145350fa51d 100644 (file)
@@ -1103,6 +1103,14 @@ static const char syntax_cases_buf23[] =
 static const char syntax_cases_expected23[] =
     "`${`${`${`${`";
 
+static const char syntax_cases_buf24[] =
+    "var a=/[[[[/]]]]/;"
+    "var b=/[[[[[/]]]]]/;";
+
+static const char syntax_cases_expected24[] =
+    "var a=/[[[[/]]]]/;"
+    "var b=/[[[[";
+
 TEST_CASE("syntax cases", "[JSNormalizer]")
 {
     SECTION("variables")
@@ -1226,7 +1234,7 @@ TEST_CASE("bad tokens", "[JSNormalizer]")
     }
 }
 
-TEST_CASE("template literal overflow", "[JSNormalizer]")
+TEST_CASE("braces overflow", "[JSNormalizer]")
 {
     SECTION("exceeding template literal limit")
     {
@@ -1234,6 +1242,12 @@ TEST_CASE("template literal overflow", "[JSNormalizer]")
         VALIDATE_FAIL(syntax_cases_buf23, syntax_cases_expected23,
             JSTokenizer::TEMPLATE_NESTING_OVERFLOW, 15);
     }
+    SECTION("exceeding regex literal limit")
+    {
+        NORMALIZE(syntax_cases_buf24);
+        VALIDATE_FAIL(syntax_cases_buf24, syntax_cases_expected24,
+            JSTokenizer::TEMPLATE_NESTING_OVERFLOW, 30);
+    }
 }
 
 static const char asi_cases_buf0[] =