summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2018-09-03 10:49:46 +0200
committerPatrick Steinhardt <ps@pks.im>2018-09-03 10:52:44 +0200
commitbc63e1ef521ab5900dc0b0dcd578b8bf18627fb1 (patch)
treef0270c12cca8104bb5895d5e03692934a5b54406
parent38b852558eb518f96c313cdcd9ce5a7af6ded194 (diff)
downloadlibgit2-bc63e1ef521ab5900dc0b0dcd578b8bf18627fb1.tar.gz
config_parse: refactor error handling when parsing multiline variables
The current error handling for the multiline variable parser is a bit fragile, as each error condition has its own code to clear memory. Instead, unify error handling as far as possible to avoid this repetitive code. While at it, make use of `GITERR_CHECK_ALLOC` to correctly handle OOM situations and verify that the buffer we print into does not run out of memory either.
-rw-r--r--src/config_parse.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/src/config_parse.c b/src/config_parse.c
index bc70eec63..282aabe17 100644
--- a/src/config_parse.c
+++ b/src/config_parse.c
@@ -315,46 +315,52 @@ done:
static int parse_multiline_variable(git_config_parser *reader, git_buf *value, int in_quotes)
{
- char *line = NULL, *proc_line = NULL;
int quote_count;
bool multiline = true;
while (multiline) {
+ char *line = NULL, *proc_line = NULL;
+ int error;
+
/* Check that the next line exists */
git_parse_advance_line(&reader->ctx);
line = git__strndup(reader->ctx.line, reader->ctx.line_len);
- if (line == NULL)
- return -1;
+ GITERR_CHECK_ALLOC(line);
- /* We've reached the end of the file, there is no continuation.
+ /*
+ * We've reached the end of the file, there is no continuation.
* (this is not an error).
*/
if (line[0] == '\0') {
- git__free(line);
- return 0;
+ error = 0;
+ goto out;
}
+ /* If it was just a comment, pretend it didn't exist */
quote_count = strip_comments(line, !!in_quotes);
+ if (line[0] == '\0')
+ goto next;
- /* If it was just a comment, pretend it didn't exist */
- if (line[0] == '\0') {
- git__free(line);
- in_quotes = quote_count;
- continue;
- }
+ if ((error = unescape_line(&proc_line, &multiline,
+ line, in_quotes)) < 0)
+ goto out;
- if (unescape_line(&proc_line, &multiline, line, in_quotes) < 0) {
- git__free(line);
- return -1;
- }
- /* add this line to the multiline var */
+ /* Add this line to the multiline var */
+ if ((error = git_buf_puts(value, proc_line)) < 0)
+ goto out;
- git_buf_puts(value, proc_line);
+next:
git__free(line);
git__free(proc_line);
-
in_quotes = quote_count;
+ continue;
+
+out:
+ git__free(line);
+ git__free(proc_line);
+ return error;
}
+
return 0;
}