diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2021-12-23 15:03:08 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-23 15:03:08 -0500 |
commit | 05c3d972be68c33fdd397d4b2cf6f090d4b3f994 (patch) | |
tree | 7deeac87d0c273cd09d0100ff2fdc0cbce8eb882 | |
parent | 3cca14b3c1182f093d7e2d9c7de8bcb8b8828163 (diff) | |
parent | dff05bc308f40fe327364334eaae412afca8ad61 (diff) | |
download | libgit2-05c3d972be68c33fdd397d4b2cf6f090d4b3f994.tar.gz |
Merge pull request #6124 from csware/config-parsing
Config parsing
-rw-r--r-- | src/config_parse.c | 14 | ||||
-rw-r--r-- | tests/config/read.c | 28 | ||||
-rw-r--r-- | tests/config/write.c | 19 | ||||
-rw-r--r-- | tests/resources/config/config22 | 10 |
4 files changed, 66 insertions, 5 deletions
diff --git a/src/config_parse.c b/src/config_parse.c index 3159cbef7..06931368e 100644 --- a/src/config_parse.c +++ b/src/config_parse.c @@ -36,7 +36,7 @@ static int strip_comments(char *line, int in_quotes) char *ptr; for (ptr = line; *ptr; ++ptr) { - if (ptr[0] == '"' && ptr > line && ptr[-1] != '\\') + if (ptr[0] == '"' && ((ptr > line && ptr[-1] != '\\') || ptr == line)) quote_count++; if ((ptr[0] == ';' || ptr[0] == '#') && @@ -325,7 +325,7 @@ done: return 0; } -static int parse_multiline_variable(git_config_parser *reader, git_str *value, int in_quotes) +static int parse_multiline_variable(git_config_parser *reader, git_str *value, int in_quotes, size_t *line_len) { int quote_count; bool multiline = true; @@ -338,6 +338,10 @@ static int parse_multiline_variable(git_config_parser *reader, git_str *value, i git_parse_advance_line(&reader->ctx); line = git__strndup(reader->ctx.line, reader->ctx.line_len); GIT_ERROR_CHECK_ALLOC(line); + if (GIT_ADD_SIZET_OVERFLOW(line_len, *line_len, reader->ctx.line_len)) { + error = -1; + goto out; + } /* * We've reached the end of the file, there is no continuation. @@ -415,7 +419,7 @@ static int parse_name( return 0; } -static int parse_variable(git_config_parser *reader, char **var_name, char **var_value) +static int parse_variable(git_config_parser *reader, char **var_name, char **var_value, size_t *line_len) { const char *value_start = NULL; char *line = NULL, *name = NULL, *value = NULL; @@ -449,7 +453,7 @@ static int parse_variable(git_config_parser *reader, char **var_name, char **var git_str_attach(&multi_value, value, 0); value = NULL; - if (parse_multiline_variable(reader, &multi_value, quote_count % 2) < 0 || + if (parse_multiline_variable(reader, &multi_value, quote_count % 2, line_len) < 0 || git_str_oom(&multi_value)) { error = -1; git_str_dispose(&multi_value); @@ -554,7 +558,7 @@ int git_config_parse( break; default: /* assume variable declaration */ - if ((result = parse_variable(parser, &var_name, &var_value)) == 0 && on_variable) { + if ((result = parse_variable(parser, &var_name, &var_value, &line_len)) == 0 && on_variable) { result = on_variable(parser, current_section, var_name, var_value, line_start, line_len, payload); git__free(var_name); git__free(var_value); diff --git a/tests/config/read.c b/tests/config/read.c index 3c96f8519..a2e668c20 100644 --- a/tests/config/read.c +++ b/tests/config/read.c @@ -209,6 +209,21 @@ void test_config_read__symbol_headers(void) { git_config *cfg; cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config20"))); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "valid.[subsection].something")); + cl_assert_equal_s("a", buf.ptr); + git_buf_dispose(&buf); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec.[subsec]/child.parent")); + cl_assert_equal_s("grand", buf.ptr); + git_buf_dispose(&buf); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec2.[subsec2]/child2.type")); + cl_assert_equal_s("dvcs", buf.ptr); + git_buf_dispose(&buf); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec3.escape\"quote.vcs")); + cl_assert_equal_s("git", buf.ptr); + git_buf_dispose(&buf); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec4.escaping\\slash.lib")); + cl_assert_equal_s("git2", buf.ptr); + git_buf_dispose(&buf); git_config_free(cfg); } @@ -219,6 +234,19 @@ void test_config_read__multiline_multiple_quoted_comment_chars(void) git_config_free(cfg); } +void test_config_read__multiline_multiple_quoted_quote_at_beginning_of_line(void) +{ + git_config* cfg; + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config22"))); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m")); + cl_assert_equal_s("cmd ;; ;; bar", buf.ptr); + git_buf_dispose(&buf); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m2")); + cl_assert_equal_s("'; ; something '", buf.ptr); + git_buf_dispose(&buf); + git_config_free(cfg); +} + void test_config_read__header_in_last_line(void) { git_config *cfg; diff --git a/tests/config/write.c b/tests/config/write.c index 4ee83833f..9d8c3fe94 100644 --- a/tests/config/write.c +++ b/tests/config/write.c @@ -8,6 +8,7 @@ void test_config_write__initialize(void) cl_fixture_sandbox("config/config9"); cl_fixture_sandbox("config/config15"); cl_fixture_sandbox("config/config17"); + cl_fixture_sandbox("config/config22"); } void test_config_write__cleanup(void) @@ -15,6 +16,7 @@ void test_config_write__cleanup(void) cl_fixture_cleanup("config9"); cl_fixture_cleanup("config15"); cl_fixture_cleanup("config17"); + cl_fixture_cleanup("config22"); } void test_config_write__replace_value(void) @@ -743,3 +745,20 @@ void test_config_write__preserve_case(void) git_config_free(cfg); } + +void test_config_write__write_config_file_with_multi_line_value(void) +{ + git_config* cfg; + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_config_open_ondisk(&cfg, "config22")); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m")); + cl_assert_equal_s("cmd ;; ;; bar", buf.ptr); + cl_git_pass(git_config_set_string(cfg, "sOMe.ThInG", "foo")); + git_buf_dispose(&buf); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m")); + cl_assert_equal_s("cmd ;; ;; bar", buf.ptr); + git_buf_dispose(&buf); + + git_config_free(cfg); +} diff --git a/tests/resources/config/config22 b/tests/resources/config/config22 new file mode 100644 index 000000000..2a8e528ff --- /dev/null +++ b/tests/resources/config/config22 @@ -0,0 +1,10 @@ +[alias] + m = cmd \ +";;" \ +";;" \ +bar + m2 = '\ +";" \ +";" \ +something \ +' |