Merge branch 'jm/maint-apply-detects-corrupt-patch-header'
authorJunio C Hamano <gitster@pobox.com>
Wed, 19 Oct 2011 17:48:29 +0000 (10:48 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 19 Oct 2011 17:48:29 +0000 (10:48 -0700)
* jm/maint-apply-detects-corrupt-patch-header:
  fix "git apply --index ..." not to deref NULL

1  2 
builtin/apply.c

diff --combined builtin/apply.c
@@@ -43,7 -43,6 +43,7 @@@ static int apply = 1
  static int apply_in_reverse;
  static int apply_with_reject;
  static int apply_verbosely;
 +static int allow_overlap;
  static int no_add;
  static const char *fake_ancestor;
  static int line_termination = '\n';
@@@ -205,7 -204,6 +205,7 @@@ struct line 
        unsigned hash : 24;
        unsigned flag : 8;
  #define LINE_COMMON     1
 +#define LINE_PATCHED  2
  };
  
  /*
@@@ -1407,6 -1405,9 +1407,9 @@@ static int find_header(char *line, unsi
                                            "%d leading pathname components (line %d)" , p_value, linenr);
                                patch->old_name = patch->new_name = patch->def_name;
                        }
+                       if (!patch->is_delete && !patch->new_name)
+                               die("git diff header lacks filename information "
+                                   "(line %d)", linenr);
                        patch->is_toplevel_relative = 1;
                        *hdrsize = git_hdr_len;
                        return offset;
@@@ -1634,7 -1635,7 +1637,7 @@@ static inline int metadata_changes(stru
  static char *inflate_it(const void *data, unsigned long size,
                        unsigned long inflated_size)
  {
 -      z_stream stream;
 +      git_zstream stream;
        void *out;
        int st;
  
@@@ -2087,8 -2088,7 +2090,8 @@@ static int match_fragment(struct image 
  
        /* Quick hash check */
        for (i = 0; i < preimage_limit; i++)
 -              if (preimage->line[i].hash != img->line[try_lno + i].hash)
 +              if ((img->line[try_lno + i].flag & LINE_PATCHED) ||
 +                  (preimage->line[i].hash != img->line[try_lno + i].hash))
                        return 0;
  
        if (preimage_limit == preimage->nr) {
@@@ -2431,15 -2431,11 +2434,15 @@@ static void update_image(struct image *
        memcpy(img->line + applied_pos,
               postimage->line,
               postimage->nr * sizeof(*img->line));
 +      if (!allow_overlap)
 +              for (i = 0; i < postimage->nr; i++)
 +                      img->line[applied_pos + i].flag |= LINE_PATCHED;
        img->nr = nr;
  }
  
  static int apply_one_fragment(struct image *img, struct fragment *frag,
 -                            int inaccurate_eof, unsigned ws_rule)
 +                            int inaccurate_eof, unsigned ws_rule,
 +                            int nth_fragment)
  {
        int match_beginning, match_end;
        const char *patch = frag->patch;
        char *old, *oldlines;
        struct strbuf newlines;
        int new_blank_lines_at_end = 0;
 +      int found_new_blank_lines_at_end = 0;
 +      int hunk_linenr = frag->linenr;
        unsigned long leading, trailing;
        int pos, applied_pos;
        struct image preimage;
                                error("invalid start of line: '%c'", first);
                        return -1;
                }
 -              if (added_blank_line)
 +              if (added_blank_line) {
 +                      if (!new_blank_lines_at_end)
 +                              found_new_blank_lines_at_end = hunk_linenr;
                        new_blank_lines_at_end++;
 +              }
                else if (is_blank_context)
                        ;
                else
                        new_blank_lines_at_end = 0;
                patch += len;
                size -= len;
 +              hunk_linenr++;
        }
        if (inaccurate_eof &&
            old > oldlines && old[-1] == '\n' &&
                    preimage.nr + applied_pos >= img->nr &&
                    (ws_rule & WS_BLANK_AT_EOF) &&
                    ws_error_action != nowarn_ws_error) {
 -                      record_ws_error(WS_BLANK_AT_EOF, "+", 1, frag->linenr);
 +                      record_ws_error(WS_BLANK_AT_EOF, "+", 1,
 +                                      found_new_blank_lines_at_end);
                        if (ws_error_action == correct_ws_error) {
                                while (new_blank_lines_at_end--)
                                        remove_last_line(&postimage);
                                apply = 0;
                }
  
 +              if (apply_verbosely && applied_pos != pos) {
 +                      int offset = applied_pos - pos;
 +                      if (apply_in_reverse)
 +                              offset = 0 - offset;
 +                      fprintf(stderr,
 +                              "Hunk #%d succeeded at %d (offset %d lines).\n",
 +                              nth_fragment, applied_pos + 1, offset);
 +              }
 +
                /*
                 * Warn if it was necessary to reduce the number
                 * of context lines.
@@@ -2808,14 -2788,12 +2811,14 @@@ static int apply_fragments(struct imag
        const char *name = patch->old_name ? patch->old_name : patch->new_name;
        unsigned ws_rule = patch->ws_rule;
        unsigned inaccurate_eof = patch->inaccurate_eof;
 +      int nth = 0;
  
        if (patch->is_binary)
                return apply_binary(img, patch);
  
        while (frag) {
 -              if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule)) {
 +              nth++;
 +              if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule, nth)) {
                        error("patch failed: %s:%ld", name, frag->oldpos);
                        if (!apply_with_reject)
                                return -1;
@@@ -3838,6 -3816,7 +3841,6 @@@ int cmd_apply(int argc, const char **ar
        int i;
        int errs = 0;
        int is_not_gitdir = !startup_info->have_repository;
 -      int binary;
        int force_apply = 0;
  
        const char *whitespace_option = NULL;
                        "ignore additions made by the patch"),
                OPT_BOOLEAN(0, "stat", &diffstat,
                        "instead of applying the patch, output diffstat for the input"),
 -              { OPTION_BOOLEAN, 0, "allow-binary-replacement", &binary,
 -                NULL, "old option, now no-op",
 -                PARSE_OPT_HIDDEN | PARSE_OPT_NOARG },
 -              { OPTION_BOOLEAN, 0, "binary", &binary,
 -                NULL, "old option, now no-op",
 -                PARSE_OPT_HIDDEN | PARSE_OPT_NOARG },
 +              OPT_NOOP_NOARG(0, "allow-binary-replacement"),
 +              OPT_NOOP_NOARG(0, "binary"),
                OPT_BOOLEAN(0, "numstat", &numstat,
                        "shows number of added and deleted lines in decimal notation"),
                OPT_BOOLEAN(0, "summary", &summary,
                        "don't expect at least one line of context"),
                OPT_BOOLEAN(0, "reject", &apply_with_reject,
                        "leave the rejected hunks in corresponding *.rej files"),
 +              OPT_BOOLEAN(0, "allow-overlap", &allow_overlap,
 +                      "allow overlapping hunks"),
                OPT__VERBOSE(&apply_verbosely, "be verbose"),
                OPT_BIT(0, "inaccurate-eof", &options,
                        "tolerate incorrectly detected missing new-line at the end of file",