Commit 9db04160a5bfcf8e7438f08b4c06a16d5e42000e

Vicent Martí 2011-06-01T12:52:50

Merge pull request #222 from carlosmn/config-bugfix Config bugfix

diff --git a/src/config_file.c b/src/config_file.c
index ace7cc8..d76c602 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');
-
 
-	while (line_src < line_end && isspace(*line_src))
-		line_src++;
+	line_len = line_end - 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, &current_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 0000000..0f8f90a
--- /dev/null
+++ b/tests/resources/config/config6
@@ -0,0 +1,5 @@
+[valid "subsection"]
+    something = true
+
+[something "else"]
+    something = false
diff --git a/tests/resources/config/config7 b/tests/resources/config/config7
new file mode 100644
index 0000000..6af6fcf
--- /dev/null
+++ b/tests/resources/config/config7
@@ -0,0 +1,5 @@
+[valid "subsection"]
+    something = a
+; we don't allow anything after closing "
+[sec "subsec"x]
+    bleh = blah
diff --git a/tests/resources/config/config8 b/tests/resources/config/config8
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/resources/config/config8
diff --git a/tests/t15-config.c b/tests/t15-config.c
index c2e146c..08a2cdb 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