On Thu, Dec 11, 2014 at 12:47:52AM +0100, Michael Haggerty wrote:
Show 19 quoted lines
> If "git update-ref --stdin" was given a "verify" command with no
> "<newvalue>" at all (not even zeros), the code was mistakenly setting
> have_old=0 (and leaving old_sha1 uninitialized). But this is
> incorrect: this command is supposed to verify that the reference
> doesn't exist. So in this case we really need old_sha1 to be set to
> null_sha1 and have_old to be set to 1.
>
> Moreover, since have_old was being set to zero, *no* check of the old
> value was being done, so the new value of the reference was being set
> unconditionally to the value in new_sha1. new_sha1, in turn, was set
> to null_sha1 in the expectation that that was the old value and it
> shouldn't be changed. But because the precondition was not being
> checked, the result was that the reference was being deleted
> unconditionally.
>
> So, if <oldvalue> is missing, set have_old unconditionally and set
> old_sha1 to null_sha1.
>
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Show 66 quoted lines
> ---
> builtin/update-ref.c | 14 +++++---------
> t/t1400-update-ref.sh | 4 ++--
> 2 files changed, 7 insertions(+), 11 deletions(-)
>
> diff --git a/builtin/update-ref.c b/builtin/update-ref.c
> index 6c9be05..1993529 100644
> --- a/builtin/update-ref.c
> +++ b/builtin/update-ref.c
> @@ -282,26 +282,22 @@ static const char *parse_cmd_verify(struct ref_transaction *transaction,
> char *refname;
> unsigned char new_sha1[20];
> unsigned char old_sha1[20];
> - int have_old;
>
> refname = parse_refname(input, &next);
> if (!refname)
> die("verify: missing <ref>");
>
> if (parse_next_sha1(input, &next, old_sha1, "verify", refname,
> - PARSE_SHA1_OLD)) {
> - hashclr(new_sha1);
> - have_old = 0;
> - } else {
> - hashcpy(new_sha1, old_sha1);
> - have_old = 1;
> - }
> + PARSE_SHA1_OLD))
> + hashclr(old_sha1);
> +
> + hashcpy(new_sha1, old_sha1);
>
> if (*next != line_termination)
> die("verify %s: extra input: %s", refname, next);
>
> if (ref_transaction_update(transaction, refname, new_sha1, old_sha1,
> - update_flags, have_old, msg, &err))
> + update_flags, 1, msg, &err))
> die("%s", err.buf);
>
> update_flags = 0;
> diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
> index 6a3cdd1..6805b9e 100755
> --- a/t/t1400-update-ref.sh
> +++ b/t/t1400-update-ref.sh
> @@ -655,7 +655,7 @@ test_expect_success 'stdin verify fails for mistaken null value' '
> test_cmp expect actual
> '
>
> -test_expect_failure 'stdin verify fails for mistaken empty value' '
> +test_expect_success 'stdin verify fails for mistaken empty value' '
> M=$(git rev-parse $m) &&
> test_when_finished "git update-ref $m $M" &&
> git rev-parse $m >expect &&
> @@ -1020,7 +1020,7 @@ test_expect_success 'stdin -z verify fails for mistaken null value' '
> test_cmp expect actual
> '
>
> -test_expect_failure 'stdin -z verify fails for mistaken empty value' '
> +test_expect_success 'stdin -z verify fails for mistaken empty value' '
> M=$(git rev-parse $m) &&
> test_when_finished "git update-ref $m $M" &&
> git rev-parse $m >expect &&
> --
> 2.1.3
>