From: Juhasz Viktor <jviktor@balabit.hu> the '\' is parsed by lexer and the template_compile used this character to escaping. It was confusing. Now, it has to be used $$ for printing literal $ in the result The other modification is the escaping of the '@' if it follows macro or temlate function. if non-numeric value follows the '@', use the '@' as a literal '@', but show a warning message. It has to be used '@@' for printing literal '@' in the result Signed-off-by: Juhasz Viktor <jviktor@balabit.hu> --- lib/template/templates.c | 33 +++++++++++++++++++++++----- lib/template/tests/test_template_compile.c | 25 +++++++++++++++++++-- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/lib/template/templates.c b/lib/template/templates.c index 436d645..442a7ec 100644 --- a/lib/template/templates.c +++ b/lib/template/templates.c @@ -882,13 +882,27 @@ parse_msg_ref(LogTemplateCompiler *self) if ((*self->cursor) == '@') { self->cursor++; - /* syntax: ${name}@1 to denote the log message index in the correllation state */ - while ((*self->cursor) >= '0' && (*self->cursor) <= '9') + if ((*self->cursor) >= '0' && (*self->cursor) <= '9') { - self->msg_ref += self->msg_ref * 10 + ((*self->cursor) - '0'); - self->cursor++; + /* syntax: ${name}@1 to denote the log message index in the correllation state */ + while ((*self->cursor) >= '0' && (*self->cursor) <= '9') + { + self->msg_ref += self->msg_ref * 10 + ((*self->cursor) - '0'); + self->cursor++; + } + self->msg_ref += 1; + } + else + { + if ((*self->cursor) != '@') + { + msg_warning("Non-numeric correlation state ID found, assuming a literal '@' character. To avoid confusion when using a literal '@' after a macro or template function, write '@@' in the template.", + evt_tag_str("Template", self->template->template), + NULL); + self->cursor--; + } + self->msg_ref = 0; } - self->msg_ref += 1; } } @@ -1171,7 +1185,14 @@ log_template_compiler_process_token(LogTemplateCompiler *self, GError **error) } if (*self->cursor == '\\') { - self->cursor++; + if (cfg_is_config_version_older(self->template->cfg, 0x305)) + { + msg_warning("Template escaping changed in version 3.5. Use '$$' to specify a literal dollar sign instead of '\\$' and remove the escaping of the backslash character when you upgrade your configuration", + evt_tag_str("Template", self->template->template), + NULL); + self->cursor++; + } + } if (*self->cursor) { diff --git a/lib/template/tests/test_template_compile.c b/lib/template/tests/test_template_compile.c index efebfdd..21e1885 100644 --- a/lib/template/tests/test_template_compile.c +++ b/lib/template/tests/test_template_compile.c @@ -203,17 +203,22 @@ static void test_macro_with_invalid_msgref_are_recognized_as_the_top_element_in_the_stack(void) { assert_template_compile("${MESSAGE}@gmail.com"); - assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 1); + assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); select_next_element(); - assert_compiled_template(text = "gmail.com", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); + assert_compiled_template(text = "@gmail.com", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_dollar_prefixed_with_backslash_is_a_literal_dollar(void) { + cfg_set_version(configuration, 0x304); assert_template_compile("Test \\$STRING"); assert_compiled_template(text = "Test $STRING", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); + + cfg_set_version(configuration, 0x305); + assert_template_compile("Test \\$STRING"); + assert_compiled_template(text = "Test \\", default_value = NULL, value_handle = log_msg_get_value_handle("STRING"), type = LTE_VALUE, msg_ref = 0); } static void @@ -250,8 +255,23 @@ test_dollar_with_an_invalid_macro_name_without_braces_is_parsed_as_a_literal_dol static void test_backslash_without_finishing_the_escape_sequence_is_ignored(void) { + cfg_set_version(configuration, 0x304); assert_template_compile("foo\\"); assert_compiled_template(text = "foo", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); + + cfg_set_version(configuration, 0x305); + assert_template_compile("foo\\"); + assert_compiled_template(text = "foo\\", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); +} + +static void +test_double_at_is_a_literal_at(void) +{ + assert_template_compile("${MESSAGE}@@12"); + assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); + + select_next_element(); + assert_compiled_template(text = "@12", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void @@ -270,6 +290,7 @@ test_template_compile_macro(void) TEMPLATE_TESTCASE(test_double_dollars_is_a_literal_dollar); TEMPLATE_TESTCASE(test_dollar_with_an_invalid_macro_name_without_braces_is_parsed_as_a_literal_dollar); TEMPLATE_TESTCASE(test_backslash_without_finishing_the_escape_sequence_is_ignored); + TEMPLATE_TESTCASE(test_double_at_is_a_literal_at); } static void -- 1.7.9.5