From mboxrd@z Thu Jan 1 00:00:00 1970 From: Pete Wyckoff Subject: [PATCHv3] fast-import: tighten parsing of mark references Date: Wed, 4 Apr 2012 21:51:21 -0400 Message-ID: <20120405015121.GA10945@padd.com> References: <20120401225407.GA12127@padd.com> <1333417910-17955-1-git-send-email-pw@padd.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: Jonathan Nieder , Dmitry Ivankov , David Barr , Sverre Rabbelier , Junio C Hamano , Johan Herland To: git@vger.kernel.org X-From: git-owner@vger.kernel.org Thu Apr 05 03:51:35 2012 Return-path: Envelope-to: gcvg-git-2@plane.gmane.org Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1SFbrJ-00080a-TG for gcvg-git-2@plane.gmane.org; Thu, 05 Apr 2012 03:51:34 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752458Ab2DEBv1 (ORCPT ); Wed, 4 Apr 2012 21:51:27 -0400 Received: from honk.padd.com ([74.3.171.149]:55762 "EHLO honk.padd.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751788Ab2DEBv0 (ORCPT ); Wed, 4 Apr 2012 21:51:26 -0400 Received: from arf.padd.com (unknown [50.55.145.32]) by honk.padd.com (Postfix) with ESMTPSA id 651062CBE; Wed, 4 Apr 2012 18:51:25 -0700 (PDT) Received: by arf.padd.com (Postfix, from userid 7770) id 9308A313D1; Wed, 4 Apr 2012 21:51:21 -0400 (EDT) Content-Disposition: inline In-Reply-To: <1333417910-17955-1-git-send-email-pw@padd.com> Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Archived-At: The syntax for the use of mark references in fast-import demands either a SP (space) or LF (end-of-line) after a mark reference. Fast-import does not complain when garbage appears after a mark reference in some cases. Factor out parsing of mark references and complain if errant characters are found. Buggy input can cause fast-import to produce the wrong output, silently, without error. This makes it difficult to track down buggy generators of fast-import streams. An example is seen in the last line of this commit command: commit refs/heads/S2 committer Name 1112912893 -0400 data <idx.sha1); - p = x; - } else if (!prefixcmp(p, "inline")) { + } else if (!prefixcmp(p, "inline ")) { inline_data = 1; - p += 6; + p += strlen("inline"); /* advance to space */ } else { if (get_sha1_hex(p, sha1)) die("Invalid SHA1: %s", command_buf.buf); oe = find_object(sha1); p += 40; + if (*p != ' ') + die("Missing space after SHA1: %s", command_buf.buf); } - if (*p++ != ' ') - die("Missing space after SHA1: %s", command_buf.buf); + assert(*p == ' '); + ++p; /* skip space */ strbuf_reset(&uq); if (!unquote_c_style(&uq, p, &endp)) { @@ -2407,21 +2460,21 @@ static void note_change_n(struct branch *b, unsigned char *old_fanout) /* Now parse the notemodify command. */ /* or 'inline' */ if (*p == ':') { - char *x; - oe = find_mark(strtoumax(p + 1, &x, 10)); + oe = find_mark(parse_mark_ref_space(&p)); hashcpy(sha1, oe->idx.sha1); - p = x; - } else if (!prefixcmp(p, "inline")) { + } else if (!prefixcmp(p, "inline ")) { inline_data = 1; - p += 6; + p += strlen("inline"); /* advance to space */ } else { if (get_sha1_hex(p, sha1)) die("Invalid SHA1: %s", command_buf.buf); oe = find_object(sha1); p += 40; + if (*p != ' ') + die("Missing space after SHA1: %s", command_buf.buf); } - if (*p++ != ' ') - die("Missing space after SHA1: %s", command_buf.buf); + assert(*p == ' '); + ++p; /* skip space */ /* */ s = lookup_branch(p); @@ -2430,7 +2483,7 @@ static void note_change_n(struct branch *b, unsigned char *old_fanout) die("Can't add a note on empty branch."); hashcpy(commit_sha1, s->sha1); } else if (*p == ':') { - uintmax_t commit_mark = strtoumax(p + 1, NULL, 10); + uintmax_t commit_mark = parse_mark_ref_eol(p); struct object_entry *commit_oe = find_mark(commit_mark); if (commit_oe->type != OBJ_COMMIT) die("Mark :%" PRIuMAX " not a commit", commit_mark); @@ -2537,7 +2590,7 @@ static int parse_from(struct branch *b) hashcpy(b->branch_tree.versions[0].sha1, t); hashcpy(b->branch_tree.versions[1].sha1, t); } else if (*from == ':') { - uintmax_t idnum = strtoumax(from + 1, NULL, 10); + uintmax_t idnum = parse_mark_ref_eol(from); struct object_entry *oe = find_mark(idnum); if (oe->type != OBJ_COMMIT) die("Mark :%" PRIuMAX " not a commit", idnum); @@ -2572,7 +2625,7 @@ static struct hash_list *parse_merge(unsigned int *count) if (s) hashcpy(n->sha1, s->sha1); else if (*from == ':') { - uintmax_t idnum = strtoumax(from + 1, NULL, 10); + uintmax_t idnum = parse_mark_ref_eol(from); struct object_entry *oe = find_mark(idnum); if (oe->type != OBJ_COMMIT) die("Mark :%" PRIuMAX " not a commit", idnum); @@ -2735,7 +2788,7 @@ static void parse_new_tag(void) type = OBJ_COMMIT; } else if (*from == ':') { struct object_entry *oe; - from_mark = strtoumax(from + 1, NULL, 10); + from_mark = parse_mark_ref_eol(from); oe = find_mark(from_mark); type = oe->type; hashcpy(sha1, oe->idx.sha1); @@ -2867,14 +2920,9 @@ static void parse_cat_blob(void) /* cat-blob SP LF */ p = command_buf.buf + strlen("cat-blob "); if (*p == ':') { - char *x; - oe = find_mark(strtoumax(p + 1, &x, 10)); - if (x == p + 1) - die("Invalid mark: %s", command_buf.buf); + oe = find_mark(parse_mark_ref_eol(p)); if (!oe) die("Unknown mark: %s", command_buf.buf); - if (*x) - die("Garbage after mark: %s", command_buf.buf); hashcpy(sha1, oe->idx.sha1); } else { if (get_sha1_hex(p, sha1)) @@ -2944,13 +2992,9 @@ static struct object_entry *parse_treeish_dataref(const char **p) struct object_entry *e; if (**p == ':') { /* */ - char *endptr; - e = find_mark(strtoumax(*p + 1, &endptr, 10)); - if (endptr == *p + 1) - die("Invalid mark: %s", command_buf.buf); + e = find_mark(parse_mark_ref_space(p)); if (!e) die("Unknown mark: %s", command_buf.buf); - *p = endptr; hashcpy(sha1, e->idx.sha1); } else { /* */ if (get_sha1_hex(*p, sha1)) diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 0f5b5e5..cbc0e81 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -2635,4 +2635,280 @@ test_expect_success \ 'n=$(grep $a verify | wc -l) && test 1 = $n' +### +### series S +### +# +# Setup is roughly this. Commits marked 1,2,3,4. Blobs +# marked 100 + commit. Notes 200 +. Make sure missing spaces +# and EOLs after mark references cause errors. +# +# The error message looks like either: +# Missing space after .. +# or +# Garbage after .. +# +# 1--2--4 +# \ / +# -3- +# +test_tick + +cat >input < $GIT_COMMITTER_DATE +data < $GIT_COMMITTER_DATE +data <err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <err && + commit refs/heads/Snotes + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <err + commit refs/heads/S2 + mark :3 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data < $GIT_COMMITTER_DATE + data <err && + commit refs/heads/S + mark :4 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <err && + tag refs/tags/Stag + from :2x + tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <err && + cat-blob :2x + EOF + cat err && + test_i18ngrep "after mark" err +' + +# +# ls markref +# +test_expect_success 'S: ls with garbage after mark must fail' ' + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + ls :2x hello.c + EOF + cat err && + test_i18ngrep "space after mark" err +' + +test_expect_success 'S: ls with garbage after sha1 must fail' ' + sha1=$(grep -w :2 marks | cut -d\ -f2) && + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + ls ${sha1}x hello.c + EOF + cat err && + test_i18ngrep "space after tree-ish" err +' + test_done -- 1.7.10.rc2.62.gac32b.dirty