summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNelson Elhage <nelhage@nelhage.com>2018-08-25 17:04:39 +0000
committerNelson Elhage <nelhage@nelhage.com>2018-08-25 17:08:04 +0000
commita03113e80332fba6c77f43b21d398caad50b4b89 (patch)
tree94a7cd5d037bb4ca3fe1c1ea8eeb791fe80d53f9
parent8856337b35ad417db9fa5604f76086528cb0436b (diff)
downloadlibgit2-a03113e80332fba6c77f43b21d398caad50b4b89.tar.gz
config: convert unbounded recursion into a loop
-rw-r--r--src/config_parse.c65
1 files changed, 30 insertions, 35 deletions
diff --git a/src/config_parse.c b/src/config_parse.c
index eed6cf3a2..d40d47feb 100644
--- a/src/config_parse.c
+++ b/src/config_parse.c
@@ -317,48 +317,43 @@ static int parse_multiline_variable(git_config_parser *reader, git_buf *value, i
{
char *line = NULL, *proc_line = NULL;
int quote_count;
- bool multiline;
+ bool multiline = true;
- /* 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;
+ while (multiline) {
+ /* 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;
- /* 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;
- }
-
- quote_count = strip_comments(line, !!in_quotes);
+ /* 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;
+ }
- /* If it was just a comment, pretend it didn't exist */
- if (line[0] == '\0') {
- git__free(line);
- return parse_multiline_variable(reader, value, quote_count);
- /* TODO: unbounded recursion. This **could** be exploitable */
- }
+ quote_count = strip_comments(line, !!in_quotes);
- if (unescape_line(&proc_line, &multiline, line, in_quotes) < 0) {
- git__free(line);
- return -1;
- }
- /* add this line to the multiline var */
+ /* If it was just a comment, pretend it didn't exist */
+ if (line[0] == '\0') {
+ in_quotes = quote_count;
+ continue;
+ }
- git_buf_puts(value, proc_line);
- git__free(line);
- git__free(proc_line);
+ if (unescape_line(&proc_line, &multiline, line, in_quotes) < 0) {
+ git__free(line);
+ return -1;
+ }
+ /* add this line to the multiline var */
- /*
- * If we need to continue reading the next line, let's just
- * keep putting stuff in the buffer
- */
- if (multiline)
- return parse_multiline_variable(reader, value, quote_count);
+ git_buf_puts(value, proc_line);
+ git__free(line);
+ git__free(proc_line);
+ in_quotes = quote_count;
+ }
return 0;
}