settings: Support CRLF in settings parser
authorTobias Brunner <tobias@strongswan.org>
Mon, 13 Jul 2015 09:58:21 +0000 (11:58 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 23 May 2018 10:01:45 +0000 (12:01 +0200)
src/libstrongswan/settings/settings_lexer.l
src/libstrongswan/tests/suites/test_settings.c

index ce9d4ee..48e16de 100644 (file)
@@ -56,8 +56,8 @@ static void include_files(parser_helper_t *ctx);
 
 %%
 
-[\t ]*#[^\n]*                  /* eat comments */
-[\t ]+                                 /* eat whitespace */
+[\t ]*#[^\r\n]*                        /* eat comments */
+[\t\r ]+                               /* eat whitespace */
 \n|#.*\n                               return NEWLINE; /* also eats comments at the end of a line */
 
 "{"                                            |
@@ -74,12 +74,13 @@ static void include_files(parser_helper_t *ctx);
        yy_push_state(str, yyscanner);
 }
 
-[^#{}="\n\t ]+                 {
+[^#{}="\r\n\t ]+                       {
        yylval->s = strdup(yytext);
        return NAME;
 }
 
 <inc>{
+       \r                                      /* just ignore these */
        /* we allow all characters except #, } and spaces, they can be escaped */
        <<EOF>>                         |
        [#}\n\t ]                       {
@@ -111,12 +112,13 @@ static void include_files(parser_helper_t *ctx);
        \\["#} ]                        {
                yyextra->string_add(yyextra, yytext+1);
        }
-       [^"\\#}\n\t ]+ {
+       [^"\\#}\r\n\t ]+ {
                yyextra->string_add(yyextra, yytext);
        }
 }
 
 <str>{
+       \r                                      /* just ignore these */
        "\""                            |
        <<EOF>>                         |
        \\                                      {
@@ -138,12 +140,13 @@ static void include_files(parser_helper_t *ctx);
                        return STRING;
                }
        }
+
        \\n     yyextra->string_add(yyextra, "\n");
        \\r     yyextra->string_add(yyextra, "\r");
        \\t     yyextra->string_add(yyextra, "\t");
-       \\\r?\n /* merge lines that end with EOL characters */
+       \\\r?\n /* merge lines that end with escaped EOL characters */
        \\.     yyextra->string_add(yyextra, yytext+1);
-       [^\\"]+                 {
+       [^\\\r"]+                       {
                yyextra->string_add(yyextra, yytext);
        }
 }
index 9d0a6de..d291b16 100644 (file)
@@ -1154,6 +1154,104 @@ START_TEST(test_invalid)
 }
 END_TEST
 
+START_SETUP(setup_crlf_config)
+{
+       chunk_t inc1 = chunk_from_str(
+               "main {\r\n"
+               "       key1 = n1\r\n"
+               "       key2 = n2\n"
+               "       key3 = val3\n"
+               "       none = \n"
+               "       sub1 {\n"
+               "               key3 = value\n"
+               "       }\n"
+               "       sub2 {\n"
+               "               sub3 = val3\n"
+               "       }\n"
+               "       include " include2 "\n"
+               "}");
+       chunk_t inc2 = chunk_from_str(
+               "key2 = v2\n"
+               "sub1 {\n"
+               "       key = val\n"
+               "}");
+       ck_assert(chunk_write(inc1, include1, 0022, TRUE));
+       ck_assert(chunk_write(inc2, include2, 0022, TRUE));
+}
+END_SETUP
+
+START_TEST(test_crlf)
+{
+       chunk_t contents = chunk_from_str(
+               "main {\r\n"
+               "       key1 = val1\r\n"
+               "       none =\r\n"
+               "       sub1 {\r\n"
+               "               key2 = v2\r\n"
+               "               # key2 = v3\r\n"
+               "               sub1 {\r\n"
+               "                       key = val\r\n"
+               "               }\r\n"
+               "       }\r\n"
+               "}");
+
+       create_settings(contents);
+
+       verify_string("val1", "main.key1");
+       verify_string("v2", "main.sub1.key2");
+       verify_string("val", "main.sub1.sub1.key");
+       verify_null("main.none");
+}
+END_TEST
+
+START_TEST(test_crlf_string)
+{
+       chunk_t contents = chunk_from_str(
+               "main {\r\n"
+               "       key1 = \"new\r\nline\"\r\n"
+               "       key2 = \"joi\\\r\nned\"\r\n"
+               "       none =\r\n"
+               "       sub1 {\r\n"
+               "               key2 = v2\r\n"
+               "               sub1 {\r\n"
+               "                       key = val\r\n"
+               "               }\r\n"
+               "       }\r\n"
+               "}");
+
+       create_settings(contents);
+
+       verify_string("new\nline", "main.key1");
+       verify_string("joined", "main.key2");
+       verify_string("v2", "main.sub1.key2");
+       verify_string("val", "main.sub1.sub1.key");
+       verify_null("main.none");
+}
+END_TEST
+
+START_TEST(test_crlf_include)
+{
+       chunk_t contents = chunk_from_str(
+               "main {\r\n"
+               "       key1 = val1\r\n"
+               "       none =\r\n"
+               "       sub1 {\r\n"
+               "               key2 = v2\r\n"
+               "               sub1 {\r\n"
+               "                       key = val\r\n"
+               "               }\r\n"
+               "       }\r\n"
+               "}");
+
+       create_settings(contents);
+
+       verify_string("val1", "main.key1");
+       verify_string("v2", "main.sub1.key2");
+       verify_string("val", "main.sub1.sub1.key");
+       verify_null("main.none");
+}
+END_TEST
+
 Suite *settings_suite_create()
 {
        Suite *s;
@@ -1241,5 +1339,12 @@ Suite *settings_suite_create()
        tcase_add_test(tc, test_invalid);
        suite_add_tcase(s, tc);
 
+       tc = tcase_create("crlf");
+       tcase_add_checked_fixture(tc, setup_crlf_config, teardown_include_config);
+       tcase_add_test(tc, test_crlf);
+       tcase_add_test(tc, test_crlf_string);
+       tcase_add_test(tc, test_crlf_include);
+       suite_add_tcase(s, tc);
+
        return s;
 }