From ba7805b61398dc2046e9e1bd34e5e5ea0d2fd347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= Date: Tue, 21 Nov 2023 16:42:41 -1000 Subject: [PATCH] patterndb: Add support for nested quotted string in @QSTRING@ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using 2 chars to match quoted strings (e.g. `(), `[]`, `{}`), we want to detect nesting to capture the whole containing expression. Matching `(foo (bar (baz) qux)) quux` against `@QSTRING::()@` previously captured `(foo (bar (baz)` and now capture `(foo (bar (baz) qux))`. Fixes: #4716 Signed-off-by: Romain Tartière --- modules/correlation/radix.c | 44 +++++++++++++++++--------- modules/correlation/tests/test_radix.c | 15 +++++++++ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/modules/correlation/radix.c b/modules/correlation/radix.c index 12763659a9c..e55c3ae2348 100644 --- a/modules/correlation/radix.c +++ b/modules/correlation/radix.c @@ -52,23 +52,42 @@ r_parser_string(gchar *str, gint *len, const gchar *param, gpointer state, RPars gboolean r_parser_qstring(gchar *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { - gchar *end; + gchar start_char = param[0]; + gchar stop_char = param[1] ? param[1] : param[0]; + + int nesting_level = 0; + + gchar *end = str + 1; - if ((end = strchr(str + 1, ((gchar *)&state)[0])) != NULL) + while (*end) { - *len = (end - str) + 1; + if (*end == stop_char) + { + if (nesting_level) + nesting_level--; + else + { + *len = (end - str) + 1; - if (match) + if (match) + { + /* skip starting and ending quote */ + match->ofs = 1; + match->len = -2; + } + + return TRUE; + } + } + else if (*end == start_char) { - /* skip starting and ending quote */ - match->ofs = 1; - match->len = -2; + nesting_level++; } - return TRUE; + end++; } - else - return FALSE; + + return FALSE; } gboolean @@ -767,11 +786,6 @@ r_new_pnode(gchar *key, const gchar *capture_prefix) parser_node->parser_type = RPT_QSTRING; parser_node->first = params[2][0]; parser_node->last = params[2][0]; - - if (params_len >= 2 && params[2] && strlen(params[2]) == 2) - state[0] = params[2][1]; - else - state[0] = params[2][0]; } else { diff --git a/modules/correlation/tests/test_radix.c b/modules/correlation/tests/test_radix.c index 6e95e82b8ab..a1fabaca651 100644 --- a/modules/correlation/tests/test_radix.c +++ b/modules/correlation/tests/test_radix.c @@ -730,6 +730,21 @@ ParameterizedTestParameters(dbparser, test_radix_search_matches) .key = "'quoted string' hehehe", .expected_pattern = {"qstring", "quoted string", NULL} }, + { + .node_to_insert = {"@QSTRING:qstring:()@", NULL}, + .key = "(quoted string) hehehe", + .expected_pattern = {"qstring", "quoted string", NULL} + }, + { + .node_to_insert = {"@QSTRING:qstring:()@", NULL}, + .key = "(nested (quoted string())) hehehe", + .expected_pattern = {"qstring", "nested (quoted string())", NULL} + }, + { + .node_to_insert = {"@QSTRING:qstring:()@", NULL}, + .key = "(unbalanced (nested (quoted string())) hehehe", + .expected_pattern = {NULL} + }, { .node_to_insert = {"@QSTRING:qstring:'@", NULL}, .key = "v12345",