]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'pw/add-p-leakfix'
authorJunio C Hamano <gitster@pobox.com>
Sat, 19 Sep 2020 00:58:03 +0000 (17:58 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 19 Sep 2020 00:58:03 +0000 (17:58 -0700)
Leakfix.

* pw/add-p-leakfix:
  add -p: fix memory leak

1  2 
add-patch.c

diff --combined add-patch.c
index 457b8c550eb1b9711a67ceda65c27841ee7e3150,87db599e9c873c1513f1f71079d0ccb79a22b45a..2fcab983a64882b2bccadeac8fce52566f8a9bb5
@@@ -2,7 -2,7 +2,7 @@@
  #include "add-interactive.h"
  #include "strbuf.h"
  #include "run-command.h"
 -#include "argv-array.h"
 +#include "strvec.h"
  #include "pathspec.h"
  #include "color.h"
  #include "diff.h"
@@@ -266,6 -266,20 +266,20 @@@ struct add_p_state 
        const char *revision;
  };
  
+ static void add_p_state_clear(struct add_p_state *s)
+ {
+       size_t i;
+       strbuf_release(&s->answer);
+       strbuf_release(&s->buf);
+       strbuf_release(&s->plain);
+       strbuf_release(&s->colored);
+       for (i = 0; i < s->file_diff_nr; i++)
+               free(s->file_diff[i].hunk);
+       free(s->file_diff);
+       clear_add_i_state(&s->s);
+ }
  static void err(struct add_p_state *s, const char *fmt, ...)
  {
        va_list args;
@@@ -286,12 -300,12 +300,12 @@@ static void setup_child_process(struct 
  
        va_start(ap, cp);
        while ((arg = va_arg(ap, const char *)))
 -              argv_array_push(&cp->args, arg);
 +              strvec_push(&cp->args, arg);
        va_end(ap);
  
        cp->git_cmd = 1;
 -      argv_array_pushf(&cp->env_array,
 -                       INDEX_ENVIRONMENT "=%s", s->s.r->index_file);
 +      strvec_pushf(&cp->env_array,
 +                   INDEX_ENVIRONMENT "=%s", s->s.r->index_file);
  }
  
  static int parse_range(const char **p,
@@@ -370,7 -384,7 +384,7 @@@ static int is_octal(const char *p, size
  
  static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
  {
 -      struct argv_array args = ARGV_ARRAY_INIT;
 +      struct strvec args = STRVEC_INIT;
        const char *diff_algorithm = s->s.interactive_diff_algorithm;
        struct strbuf *plain = &s->plain, *colored = NULL;
        struct child_process cp = CHILD_PROCESS_INIT;
        struct hunk *hunk = NULL;
        int res;
  
 -      argv_array_pushv(&args, s->mode->diff_cmd);
 +      strvec_pushv(&args, s->mode->diff_cmd);
        if (diff_algorithm)
 -              argv_array_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
 +              strvec_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
        if (s->revision) {
                struct object_id oid;
 -              argv_array_push(&args,
 -                              /* could be on an unborn branch */
 -                              !strcmp("HEAD", s->revision) &&
 -                              get_oid("HEAD", &oid) ?
 -                              empty_tree_oid_hex() : s->revision);
 +              strvec_push(&args,
 +                          /* could be on an unborn branch */
 +                          !strcmp("HEAD", s->revision) &&
 +                          get_oid("HEAD", &oid) ?
 +                          empty_tree_oid_hex() : s->revision);
        }
 -      color_arg_index = args.argc;
 +      color_arg_index = args.nr;
        /* Use `--no-color` explicitly, just in case `diff.color = always`. */
 -      argv_array_pushl(&args, "--no-color", "-p", "--", NULL);
 +      strvec_pushl(&args, "--no-color", "-p", "--", NULL);
        for (i = 0; i < ps->nr; i++)
 -              argv_array_push(&args, ps->items[i].original);
 +              strvec_push(&args, ps->items[i].original);
  
        setup_child_process(s, &cp, NULL);
 -      cp.argv = args.argv;
 +      cp.argv = args.v;
        res = capture_command(&cp, plain, 0);
        if (res) {
 -              argv_array_clear(&args);
 +              strvec_clear(&args);
                return error(_("could not parse diff"));
        }
        if (!plain->len) {
 -              argv_array_clear(&args);
 +              strvec_clear(&args);
                return 0;
        }
        strbuf_complete_line(plain);
                const char *diff_filter = s->s.interactive_diff_filter;
  
                setup_child_process(s, &colored_cp, NULL);
 -              xsnprintf((char *)args.argv[color_arg_index], 8, "--color");
 -              colored_cp.argv = args.argv;
 +              xsnprintf((char *)args.v[color_arg_index], 8, "--color");
 +              colored_cp.argv = args.v;
                colored = &s->colored;
                res = capture_command(&colored_cp, colored, 0);
 -              argv_array_clear(&args);
 +              strvec_clear(&args);
                if (res)
                        return error(_("could not parse colored diff"));
  
                colored_p = colored->buf;
                colored_pend = colored_p + colored->len;
        }
 -      argv_array_clear(&args);
 +      strvec_clear(&args);
  
        /* parse files and hunks */
        p = plain->buf;
                        eol = pend;
  
                if (starts_with(p, "diff ")) {
 -                      s->file_diff_nr++;
 -                      ALLOC_GROW(s->file_diff, s->file_diff_nr,
 +                      ALLOC_GROW_BY(s->file_diff, s->file_diff_nr, 1,
                                   file_diff_alloc);
                        file_diff = s->file_diff + s->file_diff_nr - 1;
 -                      memset(file_diff, 0, sizeof(*file_diff));
                        hunk = &file_diff->head;
                        hunk->start = p - plain->buf;
                        if (colored_p)
                                 */
                                hunk->splittable_into++;
  
 -                      file_diff->hunk_nr++;
 -                      ALLOC_GROW(file_diff->hunk, file_diff->hunk_nr,
 +                      ALLOC_GROW_BY(file_diff->hunk, file_diff->hunk_nr, 1,
                                   file_diff->hunk_alloc);
                        hunk = file_diff->hunk + file_diff->hunk_nr - 1;
 -                      memset(hunk, 0, sizeof(*hunk));
  
                        hunk->start = p - plain->buf;
                        if (colored)
                        if (file_diff->mode_change)
                                BUG("double mode change?\n\n%.*s",
                                    (int)(eol - plain->buf), plain->buf);
 -                      if (file_diff->hunk_nr++)
 +                      if (file_diff->hunk_nr)
                                BUG("mode change in the middle?\n\n%.*s",
                                    (int)(eol - plain->buf), plain->buf);
  
                         * is _part of_ the header "hunk".
                         */
                        file_diff->mode_change = 1;
 -                      ALLOC_GROW(file_diff->hunk, file_diff->hunk_nr,
 +                      ALLOC_GROW_BY(file_diff->hunk, file_diff->hunk_nr, 1,
                                   file_diff->hunk_alloc);
 -                      memset(file_diff->hunk, 0, sizeof(struct hunk));
                        file_diff->hunk->start = p - plain->buf;
                        if (colored_p)
                                file_diff->hunk->colored_start =
@@@ -1153,7 -1172,7 +1167,7 @@@ static int run_apply_check(struct add_p
  
        setup_child_process(s, &cp,
                            "apply", "--check", NULL);
 -      argv_array_pushv(&cp.args, s->mode->apply_check_args);
 +      strvec_pushv(&cp.args, s->mode->apply_check_args);
        if (pipe_command(&cp, s->buf.buf, s->buf.len, NULL, 0, NULL, 0))
                return error(_("'git apply --cached' failed"));
  
@@@ -1198,7 -1217,7 +1212,7 @@@ static int edit_hunk_loop(struct add_p_
        for (;;) {
                int res = edit_hunk_manually(s, hunk);
                if (res == 0) {
 -                      /* abandonded */
 +                      /* abandoned */
                        *hunk = backup;
                        return -1;
                }
@@@ -1352,15 -1371,6 +1366,15 @@@ static int patch_update_file(struct add
        struct child_process cp = CHILD_PROCESS_INIT;
        int colored = !!s->colored.len, quit = 0;
        enum prompt_mode_type prompt_mode_type;
 +      enum {
 +              ALLOW_GOTO_PREVIOUS_HUNK = 1 << 0,
 +              ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK = 1 << 1,
 +              ALLOW_GOTO_NEXT_HUNK = 1 << 2,
 +              ALLOW_GOTO_NEXT_UNDECIDED_HUNK = 1 << 3,
 +              ALLOW_SEARCH_AND_GOTO = 1 << 4,
 +              ALLOW_SPLIT = 1 << 5,
 +              ALLOW_EDIT = 1 << 6
 +      } permitted = 0;
  
        if (!file_diff->hunk_nr)
                return 0;
                fputs(s->buf.buf, stdout);
  
                strbuf_reset(&s->buf);
 -              if (undecided_previous >= 0)
 +              if (undecided_previous >= 0) {
 +                      permitted |= ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK;
                        strbuf_addstr(&s->buf, ",k");
 -              if (hunk_index)
 +              }
 +              if (hunk_index) {
 +                      permitted |= ALLOW_GOTO_PREVIOUS_HUNK;
                        strbuf_addstr(&s->buf, ",K");
 -              if (undecided_next >= 0)
 +              }
 +              if (undecided_next >= 0) {
 +                      permitted |= ALLOW_GOTO_NEXT_UNDECIDED_HUNK;
                        strbuf_addstr(&s->buf, ",j");
 -              if (hunk_index + 1 < file_diff->hunk_nr)
 +              }
 +              if (hunk_index + 1 < file_diff->hunk_nr) {
 +                      permitted |= ALLOW_GOTO_NEXT_HUNK;
                        strbuf_addstr(&s->buf, ",J");
 -              if (file_diff->hunk_nr > 1)
 +              }
 +              if (file_diff->hunk_nr > 1) {
 +                      permitted |= ALLOW_SEARCH_AND_GOTO;
                        strbuf_addstr(&s->buf, ",g,/");
 -              if (hunk->splittable_into > 1)
 +              }
 +              if (hunk->splittable_into > 1) {
 +                      permitted |= ALLOW_SPLIT;
                        strbuf_addstr(&s->buf, ",s");
 +              }
                if (hunk_index + 1 > file_diff->mode_change &&
 -                  !file_diff->deleted)
 +                  !file_diff->deleted) {
 +                      permitted |= ALLOW_EDIT;
                        strbuf_addstr(&s->buf, ",e");
 -
 +              }
                if (file_diff->deleted)
                        prompt_mode_type = PROMPT_DELETION;
                else if (file_diff->added)
@@@ -1474,22 -1471,22 +1488,22 @@@ soft_increment
                                break;
                        }
                } else if (s->answer.buf[0] == 'K') {
 -                      if (hunk_index)
 +                      if (permitted & ALLOW_GOTO_PREVIOUS_HUNK)
                                hunk_index--;
                        else
                                err(s, _("No previous hunk"));
                } else if (s->answer.buf[0] == 'J') {
 -                      if (hunk_index + 1 < file_diff->hunk_nr)
 +                      if (permitted & ALLOW_GOTO_NEXT_HUNK)
                                hunk_index++;
                        else
                                err(s, _("No next hunk"));
                } else if (s->answer.buf[0] == 'k') {
 -                      if (undecided_previous >= 0)
 +                      if (permitted & ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK)
                                hunk_index = undecided_previous;
                        else
                                err(s, _("No previous hunk"));
                } else if (s->answer.buf[0] == 'j') {
 -                      if (undecided_next >= 0)
 +                      if (permitted & ALLOW_GOTO_NEXT_UNDECIDED_HUNK)
                                hunk_index = undecided_next;
                        else
                                err(s, _("No next hunk"));
                        char *pend;
                        unsigned long response;
  
 -                      if (file_diff->hunk_nr < 2) {
 +                      if (!(permitted & ALLOW_SEARCH_AND_GOTO)) {
                                err(s, _("No other hunks to goto"));
                                continue;
                        }
                        regex_t regex;
                        int ret;
  
 -                      if (file_diff->hunk_nr < 2) {
 +                      if (!(permitted & ALLOW_SEARCH_AND_GOTO)) {
                                err(s, _("No other hunks to search"));
                                continue;
                        }
                        hunk_index = i;
                } else if (s->answer.buf[0] == 's') {
                        size_t splittable_into = hunk->splittable_into;
 -                      if (splittable_into < 2)
 +                      if (!(permitted & ALLOW_SPLIT))
                                err(s, _("Sorry, cannot split this hunk"));
                        else if (!split_hunk(s, file_diff,
                                             hunk - file_diff->hunk))
                                                 _("Split into %d hunks."),
                                                 (int)splittable_into);
                } else if (s->answer.buf[0] == 'e') {
 -                      if (hunk_index + 1 == file_diff->mode_change)
 +                      if (!(permitted & ALLOW_EDIT))
                                err(s, _("Sorry, cannot edit this hunk"));
                        else if (edit_hunk_loop(s, file_diff, hunk) >= 0) {
                                hunk->use = USE_HUNK;
                                           s->mode->is_reverse);
                else {
                        setup_child_process(s, &cp, "apply", NULL);
 -                      argv_array_pushv(&cp.args, s->mode->apply_args);
 +                      strvec_pushv(&cp.args, s->mode->apply_args);
                        if (pipe_command(&cp, s->buf.buf, s->buf.len,
                                         NULL, 0, NULL, 0))
                                error(_("'git apply' failed"));
@@@ -1690,9 -1687,7 +1704,7 @@@ int run_add_p(struct repository *r, enu
             repo_refresh_and_write_index(r, REFRESH_QUIET, 0, 1,
                                          NULL, NULL, NULL) < 0) ||
            parse_diff(&s, ps) < 0) {
-               strbuf_release(&s.plain);
-               strbuf_release(&s.colored);
-               clear_add_i_state(&s.s);
+               add_p_state_clear(&s);
                return -1;
        }
  
        else if (binary_count == s.file_diff_nr)
                fprintf(stderr, _("Only binary files changed.\n"));
  
-       strbuf_release(&s.answer);
-       strbuf_release(&s.buf);
-       strbuf_release(&s.plain);
-       strbuf_release(&s.colored);
-       clear_add_i_state(&s.s);
+       add_p_state_clear(&s);
        return 0;
  }