diff --git a/epan/column-utils.c b/epan/column-utils.c index 6c7b10f9a1..a9e8ac34ff 100644 --- a/epan/column-utils.c +++ b/epan/column-utils.c @@ -78,8 +78,8 @@ col_setup(column_info *cinfo, const gint num_cols) cinfo->col_last[i] = -1; } cinfo->prime_regex = g_regex_new(COL_CUSTOM_PRIME_REGEX, - (GRegexCompileFlags) (G_REGEX_ANCHORED | G_REGEX_RAW), - G_REGEX_MATCH_ANCHORED, NULL); + (GRegexCompileFlags) (G_REGEX_RAW), + 0, NULL); } static void diff --git a/epan/column-utils.h b/epan/column-utils.h index 7239583280..a213db688a 100644 --- a/epan/column-utils.h +++ b/epan/column-utils.h @@ -23,7 +23,25 @@ extern "C" { #define COL_MAX_LEN 2048 #define COL_MAX_INFO_LEN 4096 -#define COL_CUSTOM_PRIME_REGEX " *([^ \\|]+) *(?:(?:\\|\\|)|(?:or)| *$){1}" + +/* A regex to split possibly multifield custom columns into components + * + * Split on operator "||" (with optional space around it) and on "or" + * (which must have space around it to avoid matching in the middle of + * a word, field in the "synphasor" protocol, etc. This is somewhat too + * strict, as "or" adjacent to parentheses ought to be fine so long + * as the filter matches the grammar, like "(tcp.port)or(udp.port)", + * but that's the cost of using regex instead of the real parser.) + * Also split on space at the beginning or end of the expression (in + * lieu of always stripping whitespace at the beginning and end, but it + * does mean that we have to ignore any empty tokens in the result.) + * + * Use negative lookahead to avoid matching "||" or "or" that are contained + * within parentheses. Don't match if a close parenthesis comes before an + * open parenthesis. The regex doesn't help with unmatched parentheses, but + * such an expression already won't satisfy the grammar and won't compile. + */ +#define COL_CUSTOM_PRIME_REGEX "(?:^ *| *\\|\\| *| +or +| *$)(?![^(]*\\))" struct epan_dissect; diff --git a/epan/column.c b/epan/column.c index 4eeffca71f..0d836e8ed8 100644 --- a/epan/column.c +++ b/epan/column.c @@ -989,8 +989,8 @@ get_column_tooltip(const gint col) } fields = g_regex_split_simple(COL_CUSTOM_PRIME_REGEX, cfmt->custom_fields, - (GRegexCompileFlags) (G_REGEX_ANCHORED | G_REGEX_RAW), - G_REGEX_MATCH_ANCHORED); + (GRegexCompileFlags) (G_REGEX_RAW), + 0); column_tooltip = g_string_new(""); for (i = 0; i < g_strv_length(fields); i++) { @@ -1043,7 +1043,7 @@ col_finalize(column_info *cinfo) } if (col_item->col_custom_fields) { gchar **fields = g_regex_split(cinfo->prime_regex, col_item->col_custom_fields, - G_REGEX_MATCH_ANCHORED); + 0); guint i_field; for (i_field = 0; i_field < g_strv_length(fields); i_field++) { diff --git a/ui/preference_utils.c b/ui/preference_utils.c index 6ecada4fc2..749d8d745b 100644 --- a/ui/preference_utils.c +++ b/ui/preference_utils.c @@ -235,8 +235,8 @@ column_prefs_custom_resolve(const gchar* custom_field) bool resolve = false; fields = g_regex_split_simple(COL_CUSTOM_PRIME_REGEX, custom_field, - (GRegexCompileFlags) (G_REGEX_ANCHORED | G_REGEX_RAW), - G_REGEX_MATCH_ANCHORED); + (GRegexCompileFlags) (G_REGEX_RAW), + 0); for (guint i = 0; i < g_strv_length(fields); i++) { if (fields[i] && *fields[i]) { diff --git a/ui/qt/widgets/syntax_line_edit.cpp b/ui/qt/widgets/syntax_line_edit.cpp index 99ccf7bcb7..2ea83ea112 100644 --- a/ui/qt/widgets/syntax_line_edit.cpp +++ b/ui/qt/widgets/syntax_line_edit.cpp @@ -268,7 +268,8 @@ void SyntaxLineEdit::checkCustomColumn(QString fields) } gchar **splitted_fields = g_regex_split_simple(COL_CUSTOM_PRIME_REGEX, - fields.toUtf8().constData(), G_REGEX_ANCHORED, G_REGEX_MATCH_ANCHORED); + fields.toUtf8().constData(), (GRegexCompileFlags) G_REGEX_RAW, + (GRegexMatchFlags) 0); for (guint i = 0; i < g_strv_length(splitted_fields); i++) { if (splitted_fields[i] && *splitted_fields[i]) {