diff --git a/src/libstrongswan/settings/settings_lexer.l b/src/libstrongswan/settings/settings_lexer.l index 48e16de04..c45e30ce1 100644 --- a/src/libstrongswan/settings/settings_lexer.l +++ b/src/libstrongswan/settings/settings_lexer.l @@ -49,6 +49,8 @@ static void include_files(parser_helper_t *ctx); /* type of our extra data */ %option extra-type="parser_helper_t*" +/* state used to scan values */ +%x val /* state used to scan include file patterns */ %x inc /* state used to scan quoted strings */ @@ -61,8 +63,12 @@ static void include_files(parser_helper_t *ctx); \n|#.*\n return NEWLINE; /* also eats comments at the end of a line */ "{" | -"}" | -"=" return yytext[0]; +"}" return yytext[0]; + +"=" { + yy_push_state(val, yyscanner); + return yytext[0]; +} "include"[\t ]+/[^=] { yyextra->string_init(yyextra); @@ -70,8 +76,8 @@ static void include_files(parser_helper_t *ctx); } "\"" { - yyextra->string_init(yyextra); - yy_push_state(str, yyscanner); + PARSER_DBG1(yyextra, "unexpected string detected"); + return STRING_ERROR; } [^#{}="\r\n\t ]+ { @@ -79,6 +85,42 @@ static void include_files(parser_helper_t *ctx); return NAME; } +{ + \r /* just ignore these */ + [\t ]+ + <> | + [#}\n] { + if (*yytext) + { + switch (yytext[0]) + { + case '\n': + /* put the newline back to fix the line numbers */ + unput('\n'); + yy_set_bol(0); + break; + case '#': + case '}': + /* these are parsed outside of this start condition */ + unput(yytext[0]); + break; + } + } + yy_pop_state(yyscanner); + } + + "\"" { + yyextra->string_init(yyextra); + yy_push_state(str, yyscanner); + } + + /* same as above, but allow more characters */ + [^#}"\r\n\t ]+ { + yylval->s = strdup(yytext); + return NAME; + } +} + { \r /* just ignore these */ /* we allow all characters except #, } and spaces, they can be escaped */ diff --git a/src/libstrongswan/tests/suites/test_settings.c b/src/libstrongswan/tests/suites/test_settings.c index d291b1659..c203ad72e 100644 --- a/src/libstrongswan/tests/suites/test_settings.c +++ b/src/libstrongswan/tests/suites/test_settings.c @@ -1109,6 +1109,12 @@ START_TEST(test_valid) "}\n"); ck_assert(chunk_write(contents, path, 0022, TRUE)); ck_assert(settings->load_files(settings, path, FALSE)); + + contents = chunk_from_str( + "equals = a setting with = and { character"); + ck_assert(chunk_write(contents, path, 0022, TRUE)); + ck_assert(settings->load_files(settings, path, FALSE)); + verify_string("a setting with = and { character", "equals"); } END_TEST @@ -1148,7 +1154,7 @@ START_TEST(test_invalid) ck_assert(!settings->load_files(settings, path, FALSE)); contents = chunk_from_str( - "only = a single setting = per line"); + "\"unexpected\" = string"); ck_assert(chunk_write(contents, path, 0022, TRUE)); ck_assert(!settings->load_files(settings, path, FALSE)); }