Skip to content

Commit 05c3d97

Browse files
authored
Merge pull request libgit2#6124 from csware/config-parsing
Config parsing
2 parents 3cca14b + dff05bc commit 05c3d97

File tree

4 files changed

+66
-5
lines changed

4 files changed

+66
-5
lines changed

src/config_parse.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ static int strip_comments(char *line, int in_quotes)
3636
char *ptr;
3737

3838
for (ptr = line; *ptr; ++ptr) {
39-
if (ptr[0] == '"' && ptr > line && ptr[-1] != '\\')
39+
if (ptr[0] == '"' && ((ptr > line && ptr[-1] != '\\') || ptr == line))
4040
quote_count++;
4141

4242
if ((ptr[0] == ';' || ptr[0] == '#') &&
@@ -325,7 +325,7 @@ static int unescape_line(
325325
return 0;
326326
}
327327

328-
static int parse_multiline_variable(git_config_parser *reader, git_str *value, int in_quotes)
328+
static int parse_multiline_variable(git_config_parser *reader, git_str *value, int in_quotes, size_t *line_len)
329329
{
330330
int quote_count;
331331
bool multiline = true;
@@ -338,6 +338,10 @@ static int parse_multiline_variable(git_config_parser *reader, git_str *value, i
338338
git_parse_advance_line(&reader->ctx);
339339
line = git__strndup(reader->ctx.line, reader->ctx.line_len);
340340
GIT_ERROR_CHECK_ALLOC(line);
341+
if (GIT_ADD_SIZET_OVERFLOW(line_len, *line_len, reader->ctx.line_len)) {
342+
error = -1;
343+
goto out;
344+
}
341345

342346
/*
343347
* We've reached the end of the file, there is no continuation.
@@ -415,7 +419,7 @@ static int parse_name(
415419
return 0;
416420
}
417421

418-
static int parse_variable(git_config_parser *reader, char **var_name, char **var_value)
422+
static int parse_variable(git_config_parser *reader, char **var_name, char **var_value, size_t *line_len)
419423
{
420424
const char *value_start = NULL;
421425
char *line = NULL, *name = NULL, *value = NULL;
@@ -449,7 +453,7 @@ static int parse_variable(git_config_parser *reader, char **var_name, char **var
449453
git_str_attach(&multi_value, value, 0);
450454
value = NULL;
451455

452-
if (parse_multiline_variable(reader, &multi_value, quote_count % 2) < 0 ||
456+
if (parse_multiline_variable(reader, &multi_value, quote_count % 2, line_len) < 0 ||
453457
git_str_oom(&multi_value)) {
454458
error = -1;
455459
git_str_dispose(&multi_value);
@@ -554,7 +558,7 @@ int git_config_parse(
554558
break;
555559

556560
default: /* assume variable declaration */
557-
if ((result = parse_variable(parser, &var_name, &var_value)) == 0 && on_variable) {
561+
if ((result = parse_variable(parser, &var_name, &var_value, &line_len)) == 0 && on_variable) {
558562
result = on_variable(parser, current_section, var_name, var_value, line_start, line_len, payload);
559563
git__free(var_name);
560564
git__free(var_value);

tests/config/read.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,21 @@ void test_config_read__symbol_headers(void)
209209
{
210210
git_config *cfg;
211211
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config20")));
212+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "valid.[subsection].something"));
213+
cl_assert_equal_s("a", buf.ptr);
214+
git_buf_dispose(&buf);
215+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec.[subsec]/child.parent"));
216+
cl_assert_equal_s("grand", buf.ptr);
217+
git_buf_dispose(&buf);
218+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec2.[subsec2]/child2.type"));
219+
cl_assert_equal_s("dvcs", buf.ptr);
220+
git_buf_dispose(&buf);
221+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec3.escape\"quote.vcs"));
222+
cl_assert_equal_s("git", buf.ptr);
223+
git_buf_dispose(&buf);
224+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec4.escaping\\slash.lib"));
225+
cl_assert_equal_s("git2", buf.ptr);
226+
git_buf_dispose(&buf);
212227
git_config_free(cfg);
213228
}
214229

@@ -219,6 +234,19 @@ void test_config_read__multiline_multiple_quoted_comment_chars(void)
219234
git_config_free(cfg);
220235
}
221236

237+
void test_config_read__multiline_multiple_quoted_quote_at_beginning_of_line(void)
238+
{
239+
git_config* cfg;
240+
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config22")));
241+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m"));
242+
cl_assert_equal_s("cmd ;; ;; bar", buf.ptr);
243+
git_buf_dispose(&buf);
244+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m2"));
245+
cl_assert_equal_s("'; ; something '", buf.ptr);
246+
git_buf_dispose(&buf);
247+
git_config_free(cfg);
248+
}
249+
222250
void test_config_read__header_in_last_line(void)
223251
{
224252
git_config *cfg;

tests/config/write.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ void test_config_write__initialize(void)
88
cl_fixture_sandbox("config/config9");
99
cl_fixture_sandbox("config/config15");
1010
cl_fixture_sandbox("config/config17");
11+
cl_fixture_sandbox("config/config22");
1112
}
1213

1314
void test_config_write__cleanup(void)
1415
{
1516
cl_fixture_cleanup("config9");
1617
cl_fixture_cleanup("config15");
1718
cl_fixture_cleanup("config17");
19+
cl_fixture_cleanup("config22");
1820
}
1921

2022
void test_config_write__replace_value(void)
@@ -743,3 +745,20 @@ void test_config_write__preserve_case(void)
743745

744746
git_config_free(cfg);
745747
}
748+
749+
void test_config_write__write_config_file_with_multi_line_value(void)
750+
{
751+
git_config* cfg;
752+
git_buf buf = GIT_BUF_INIT;
753+
754+
cl_git_pass(git_config_open_ondisk(&cfg, "config22"));
755+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m"));
756+
cl_assert_equal_s("cmd ;; ;; bar", buf.ptr);
757+
cl_git_pass(git_config_set_string(cfg, "sOMe.ThInG", "foo"));
758+
git_buf_dispose(&buf);
759+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m"));
760+
cl_assert_equal_s("cmd ;; ;; bar", buf.ptr);
761+
git_buf_dispose(&buf);
762+
763+
git_config_free(cfg);
764+
}

tests/resources/config/config22

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[alias]
2+
m = cmd \
3+
";;" \
4+
";;" \
5+
bar
6+
m2 = '\
7+
";" \
8+
";" \
9+
something \
10+
'

0 commit comments

Comments
 (0)