From: Mike Stepanek (mstepane) Date: Tue, 12 Apr 2022 12:29:06 +0000 (+0000) Subject: Pull request #3370: JS stack limit. X-Git-Tag: 3.1.28.0~22 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=074299c36c3ea38b1e2eaec216cfbaf5dcc24a3a;p=thirdparty%2Fsnort3.git Pull request #3370: JS stack limit. Merge in SNORT/snort3 from ~OSHUMEIK/snort3:js_regex_grp_limit to master Squashed commit of the following: commit 07c377d4a4c4e3aea177047747fbe61fcf1a4b27 Author: Oleksii Shumeiko 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. --- diff --git a/src/utils/js_tokenizer.h b/src/utils/js_tokenizer.h index 15f70c900..96e0d509a 100644 --- a/src/utils/js_tokenizer.h +++ b/src/utils/js_tokenizer.h @@ -140,6 +140,9 @@ private: ALIAS_VALUE // var a = eval }; + template + using VStack = std::stack>; + public: enum JSRet { @@ -317,14 +320,14 @@ private: bool mixed_encoding_seen = false; uint8_t max_template_nesting; - std::stack> brace_depth; + VStack 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 regex_stack; + VStack regex_stack; struct { diff --git a/src/utils/js_tokenizer.l b/src/utils/js_tokenizer.l index cdfde3cd0..24c5f78af 100644 --- a/src/utils/js_tokenizer.l +++ b/src/utils/js_tokenizer.l @@ -1656,7 +1656,7 @@ void JSTokenizer::states_reset() if (tmp_buffer) switch_to_initial(); - brace_depth = std::stack>(); + brace_depth = VStack(); 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(); + regex_stack = VStack(); 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; diff --git a/src/utils/test/js_normalizer_test.cc b/src/utils/test/js_normalizer_test.cc index b516f9b27..36dffebc1 100644 --- a/src/utils/test/js_normalizer_test.cc +++ b/src/utils/test/js_normalizer_test.cc @@ -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[] =