diff --git a/src/config_file.c b/src/config_file.c index ace7cc8ff..d76c6024d 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -261,7 +261,6 @@ static int config_open(git_config_file *cfg) cleanup: cvar_list_free(&b->var_list); gitfo_free_buf(&b->reader.buffer); - free(cfg); return git__rethrow(error, "Failed to open config"); } @@ -484,15 +483,6 @@ static int cfg_peek(diskfile_backend *cfg, int flags) return ret; } -static const char *LINEBREAK_UNIX = "\\\n"; -static const char *LINEBREAK_WIN32 = "\\\r\n"; - -static int is_linebreak(const char *pos) -{ - return memcmp(pos - 1, LINEBREAK_UNIX, sizeof(LINEBREAK_UNIX)) == 0 || - memcmp(pos - 2, LINEBREAK_WIN32, sizeof(LINEBREAK_WIN32)) == 0; -} - /* * Read and consume a line, returning it in newly-allocated memory. */ @@ -503,38 +493,24 @@ static char *cfg_readline(diskfile_backend *cfg) int line_len; line_src = cfg->reader.read_ptr; + + /* Skip empty empty lines */ + while (isspace(*line_src)) + ++line_src; + line_end = strchr(line_src, '\n'); /* no newline at EOF */ if (line_end == NULL) line_end = strchr(line_src, 0); - else - while (is_linebreak(line_end)) - line_end = strchr(line_end + 1, '\n'); + line_len = line_end - line_src; - while (line_src < line_end && isspace(*line_src)) - line_src++; - - line = (char *)git__malloc((size_t)(line_end - line_src) + 1); + line = git__malloc(line_len + 1); if (line == NULL) return NULL; - line_len = 0; - while (line_src < line_end) { - - if (memcmp(line_src, LINEBREAK_UNIX, sizeof(LINEBREAK_UNIX)) == 0) { - line_src += sizeof(LINEBREAK_UNIX); - continue; - } - - if (memcmp(line_src, LINEBREAK_WIN32, sizeof(LINEBREAK_WIN32)) == 0) { - line_src += sizeof(LINEBREAK_WIN32); - continue; - } - - line[line_len++] = *line_src++; - } + memcpy(line, line_src, line_len); line[line_len] = '\0'; @@ -619,10 +595,15 @@ static int parse_section_header_ext(const char *line, const char *base_name, cha * added to the string. In case of error, jump to out */ do { + if (quote_marks == 2) { + error = git__throw(GIT_EOBJCORRUPTED, "Falied to parse ext header. Text after closing quote"); + goto out; + + } + switch (c) { case '"': - if (quote_marks++ >= 2) - return git__throw(GIT_EOBJCORRUPTED, "Failed to parse ext header. Too many quotes"); + ++quote_marks; break; case '\\': c = line[rpos++]; @@ -634,6 +615,7 @@ static int parse_section_header_ext(const char *line, const char *base_name, cha error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse ext header. Unsupported escape char \\%c", c); goto out; } + break; default: break; } @@ -820,6 +802,10 @@ static int config_parse(diskfile_backend *cfg_file) cfg_file->reader.read_ptr = cfg_file->reader.buffer.data; cfg_file->reader.eof = 0; + /* If the file is empty, there's nothing for us to do */ + if (*cfg_file->reader.read_ptr == '\0') + return GIT_SUCCESS; + skip_bom(cfg_file); while (error == GIT_SUCCESS && !cfg_file->reader.eof) { @@ -832,6 +818,7 @@ static int config_parse(diskfile_backend *cfg_file) case '[': /* section header, new section begins */ free(current_section); + current_section = NULL; error = parse_section_header(cfg_file, ¤t_section); break; @@ -871,8 +858,7 @@ static int config_parse(diskfile_backend *cfg_file) } } - if (current_section) - free(current_section); + free(current_section); return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to parse config"); } diff --git a/tests/resources/config/config6 b/tests/resources/config/config6 new file mode 100644 index 000000000..0f8f90ac9 Binary files /dev/null and b/tests/resources/config/config6 differ diff --git a/tests/resources/config/config7 b/tests/resources/config/config7 new file mode 100644 index 000000000..6af6fcf25 Binary files /dev/null and b/tests/resources/config/config7 differ diff --git a/tests/resources/config/config8 b/tests/resources/config/config8 new file mode 100644 index 000000000..e69de29bb diff --git a/tests/t15-config.c b/tests/t15-config.c index c2e146cf1..08a2cdbf2 100644 --- a/tests/t15-config.c +++ b/tests/t15-config.c @@ -159,6 +159,35 @@ BEGIN_TEST(config5, "test number suffixes") git_config_free(cfg); END_TEST +BEGIN_TEST(config6, "test blank lines") + git_config *cfg; + int i; + + must_pass(git_config_open_file(&cfg, CONFIG_BASE "/config6")); + + must_pass(git_config_get_bool(cfg, "valid.subsection.something", &i)); + must_be_true(i == 1); + + must_pass(git_config_get_bool(cfg, "something.else.something", &i)); + must_be_true(i == 0); + + git_config_free(cfg); +END_TEST + +BEGIN_TEST(config7, "test for invalid ext headers") + git_config *cfg; + + must_fail(git_config_open_file(&cfg, CONFIG_BASE "/config7")); + +END_TEST + +BEGIN_TEST(config8, "don't fail on empty files") + git_config *cfg; + + must_pass(git_config_open_file(&cfg, CONFIG_BASE "/config8")); + + git_config_free(cfg); +END_TEST BEGIN_SUITE(config) ADD_TEST(config0); @@ -167,4 +196,7 @@ BEGIN_SUITE(config) ADD_TEST(config3); ADD_TEST(config4); ADD_TEST(config5); + ADD_TEST(config6); + ADD_TEST(config7); + ADD_TEST(config8); END_SUITE