static int parse_header_start(git_patch_parsed *patch, git_patch_parse_ctx *ctx) { if (parse_header_path(&patch->header_old_path, ctx) < 0) return git_parse_err("corrupt old path in git diff header at line %"PRIuZ, ctx->parse_ctx.line_num); if (git_parse_advance_ws(&ctx->parse_ctx) < 0 || parse_header_path(&patch->header_new_path, ctx) < 0) return git_parse_err("corrupt new path in git diff header at line %"PRIuZ, ctx->parse_ctx.line_num); /* * We cannot expect to be able to always parse paths correctly at this * point. Due to the possibility of unquoted names, whitespaces in * filenames and custom prefixes we have to allow that, though, and just * proceeed here. We then hope for the "---" and "+++" lines to fix that * for us. */ if (!git_parse_ctx_contains(&ctx->parse_ctx, "\n", 1)) { git_parse_advance_chars(&ctx->parse_ctx, ctx->parse_ctx.line_len - 1); git__free(patch->header_old_path); patch->header_old_path = NULL; git__free(patch->header_new_path); patch->header_new_path = NULL; } return 0; }
static int parse_variable(git_config_parser *reader, char **var_name, char **var_value) { const char *value_start = NULL; char *line; int quote_count; bool multiline; git_parse_advance_ws(&reader->ctx); line = git__strndup(reader->ctx.line, reader->ctx.line_len); if (line == NULL) return -1; quote_count = strip_comments(line, 0); /* If there is no value, boolean true is assumed */ *var_value = NULL; if (parse_name(var_name, &value_start, reader, line) < 0) goto on_error; /* * Now, let's try to parse the value */ if (value_start != NULL) { while (git__isspace(value_start[0])) value_start++; if (unescape_line(var_value, &multiline, value_start, 0) < 0) goto on_error; if (multiline) { git_buf multi_value = GIT_BUF_INIT; git_buf_attach(&multi_value, *var_value, 0); if (parse_multiline_variable(reader, &multi_value, quote_count) < 0 || git_buf_oom(&multi_value)) { git_buf_free(&multi_value); goto on_error; } *var_value = git_buf_detach(&multi_value); } } git__free(line); return 0; on_error: git__free(*var_name); git__free(line); return -1; }
static int parse_header_git( git_patch_parsed *patch, git_patch_parse_ctx *ctx) { size_t i; int error = 0; parse_header_state state = STATE_START; /* Parse remaining header lines */ for (; ctx->parse_ctx.remain_len > 0; git_parse_advance_line(&ctx->parse_ctx)) { bool found = false; if (ctx->parse_ctx.line_len == 0 || ctx->parse_ctx.line[ctx->parse_ctx.line_len - 1] != '\n') break; for (i = 0; i < ARRAY_SIZE(transitions); i++) { const parse_header_transition *transition = &transitions[i]; size_t op_len = strlen(transition->str); if (transition->expected_state != state || git__prefixcmp(ctx->parse_ctx.line, transition->str) != 0) continue; state = transition->next_state; /* Do not advance if this is the patch separator */ if (transition->fn == NULL) goto done; git_parse_advance_chars(&ctx->parse_ctx, op_len); if ((error = transition->fn(patch, ctx)) < 0) goto done; git_parse_advance_ws(&ctx->parse_ctx); if (git_parse_advance_expected_str(&ctx->parse_ctx, "\n") < 0 || ctx->parse_ctx.line_len > 0) { error = git_parse_err("trailing data at line %"PRIuZ, ctx->parse_ctx.line_num); goto done; } found = true; break; } if (!found) { error = git_parse_err("invalid patch header at line %"PRIuZ, ctx->parse_ctx.line_num); goto done; } } if (state != STATE_END) { error = git_parse_err("unexpected header line %"PRIuZ, ctx->parse_ctx.line_num); goto done; } done: return error; }
static int parse_section_header(git_config_parser *reader, char **section_out) { char *name, *name_end; int name_length, c, pos; int result; char *line; size_t line_len; git_parse_advance_ws(&reader->ctx); line = git__strndup(reader->ctx.line, reader->ctx.line_len); if (line == NULL) return -1; /* find the end of the variable's name */ name_end = strrchr(line, ']'); if (name_end == NULL) { git__free(line); set_parse_error(reader, 0, "Missing ']' in section header"); return -1; } GITERR_CHECK_ALLOC_ADD(&line_len, (size_t)(name_end - line), 1); name = git__malloc(line_len); GITERR_CHECK_ALLOC(name); name_length = 0; pos = 0; /* Make sure we were given a section header */ c = line[pos++]; assert(c == '['); c = line[pos++]; do { if (git__isspace(c)){ name[name_length] = '\0'; result = parse_section_header_ext(reader, line, name, section_out); git__free(line); git__free(name); return result; } if (!config_keychar(c) && c != '.') { set_parse_error(reader, pos, "Unexpected character in header"); goto fail_parse; } name[name_length++] = (char)git__tolower(c); } while ((c = line[pos++]) != ']'); if (line[pos - 1] != ']') { set_parse_error(reader, pos, "Unexpected end of file"); goto fail_parse; } git__free(line); name[name_length] = 0; *section_out = name; return 0; fail_parse: git__free(line); git__free(name); return -1; }