* [PATCH 0/2] Fix a bug with update-ref "verify" and no oldvalue
@ 2014-12-10 23:47 Michael Haggerty
2014-12-10 23:47 ` [PATCH 1/2] t1400: add some more tests of "update-ref --stdin"'s verify command Michael Haggerty
2014-12-10 23:47 ` [PATCH 2/2] update-ref: fix "verify" command with missing <oldvalue> Michael Haggerty
0 siblings, 2 replies; 7+ messages in thread
From: Michael Haggerty @ 2014-12-10 23:47 UTC (permalink / raw)
To: Junio C Hamano
Cc: Brad King, Stefan Beller, Jonathan Nieder, Ronnie Sahlberg, git,
Michael Haggerty
Ever since the --stdin option was added to "git update-ref" in
c750ba9519 update-ref: support multiple simultaneous updates (2013-09-09)
the "verify" command has been broken. If no <oldvalue> is specified,
the documentation says that the "verify" command will verify that the
reference doesn't currently exist. But in fact, it unconditionally
*deletes* the reference (!)
Hopefully this is not a common usage idiom, but this is nonetheless a
serious bug.
Add some tests for this and related functionality, then fix the bug.
These patches are also available from my GitHub repository [1] as
branch "update-ref-verify-fix-v1".
This fix applies to "maint", for which I think it is appropriate. It
also merges through to "master" with no conflicts, though it conflicts
trivially with "pu".
[1] https://github.com/mhagger/git
Michael Haggerty (2):
t1400: add some more tests of "update-ref --stdin"'s verify command
update-ref: fix "verify" command with missing <oldvalue>
builtin/update-ref.c | 14 +++-----
t/t1400-update-ref.sh | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+), 9 deletions(-)
--
2.1.3
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] t1400: add some more tests of "update-ref --stdin"'s verify command
2014-12-10 23:47 [PATCH 0/2] Fix a bug with update-ref "verify" and no oldvalue Michael Haggerty
@ 2014-12-10 23:47 ` Michael Haggerty
2014-12-11 0:10 ` Stefan Beller
2014-12-11 16:19 ` Brad King
2014-12-10 23:47 ` [PATCH 2/2] update-ref: fix "verify" command with missing <oldvalue> Michael Haggerty
1 sibling, 2 replies; 7+ messages in thread
From: Michael Haggerty @ 2014-12-10 23:47 UTC (permalink / raw)
To: Junio C Hamano
Cc: Brad King, Stefan Beller, Jonathan Nieder, Ronnie Sahlberg, git,
Michael Haggerty
Two of the tests fail because
verify refs/heads/foo
with no argument (not even zeros) actually *deletes* refs/heads/foo.
This problem will be fixed in the next commit.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
The two failing tests have to restore the $m reference when they're
done because otherwise the bug deletes it, causing subsequent tests
to fail.
t/t1400-update-ref.sh | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 7b4707b..6a3cdd1 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -619,6 +619,52 @@ test_expect_success 'stdin update/create/verify combination works' '
test_must_fail git rev-parse --verify -q $c
'
+test_expect_success 'stdin verify succeeds for correct value' '
+ git rev-parse $m >expect &&
+ echo "verify $m $m" >stdin &&
+ git update-ref --stdin <stdin &&
+ git rev-parse $m >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stdin verify succeeds for missing reference' '
+ echo "verify refs/heads/missing $Z" >stdin &&
+ git update-ref --stdin <stdin &&
+ test_must_fail git rev-parse --verify -q refs/heads/missing
+'
+
+test_expect_success 'stdin verify treats no value as missing' '
+ echo "verify refs/heads/missing" >stdin &&
+ git update-ref --stdin <stdin &&
+ test_must_fail git rev-parse --verify -q refs/heads/missing
+'
+
+test_expect_success 'stdin verify fails for wrong value' '
+ git rev-parse $m >expect &&
+ echo "verify $m $m~1" >stdin &&
+ test_must_fail git update-ref --stdin <stdin &&
+ git rev-parse $m >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stdin verify fails for mistaken null value' '
+ git rev-parse $m >expect &&
+ echo "verify $m $Z" >stdin &&
+ test_must_fail git update-ref --stdin <stdin &&
+ git rev-parse $m >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure '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 &&
+ echo "verify $m" >stdin &&
+ test_must_fail git update-ref --stdin <stdin &&
+ git rev-parse $m >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'stdin update refs works with identity updates' '
cat >stdin <<-EOF &&
update $a $m $m
@@ -938,6 +984,52 @@ test_expect_success 'stdin -z update/create/verify combination works' '
test_must_fail git rev-parse --verify -q $c
'
+test_expect_success 'stdin -z verify succeeds for correct value' '
+ git rev-parse $m >expect &&
+ printf $F "verify $m" "$m" >stdin &&
+ git update-ref -z --stdin <stdin &&
+ git rev-parse $m >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stdin -z verify succeeds for missing reference' '
+ printf $F "verify refs/heads/missing" "$Z" >stdin &&
+ git update-ref -z --stdin <stdin &&
+ test_must_fail git rev-parse --verify -q refs/heads/missing
+'
+
+test_expect_success 'stdin -z verify treats no value as missing' '
+ printf $F "verify refs/heads/missing" "" >stdin &&
+ git update-ref -z --stdin <stdin &&
+ test_must_fail git rev-parse --verify -q refs/heads/missing
+'
+
+test_expect_success 'stdin -z verify fails for wrong value' '
+ git rev-parse $m >expect &&
+ printf $F "verify $m" "$m~1" >stdin &&
+ test_must_fail git update-ref -z --stdin <stdin &&
+ git rev-parse $m >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stdin -z verify fails for mistaken null value' '
+ git rev-parse $m >expect &&
+ printf $F "verify $m" "$Z" >stdin &&
+ test_must_fail git update-ref -z --stdin <stdin &&
+ git rev-parse $m >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure '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 &&
+ printf $F "verify $m" "" >stdin &&
+ test_must_fail git update-ref -z --stdin <stdin &&
+ git rev-parse $m >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'stdin -z update refs works with identity updates' '
printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "$Z" "" >stdin &&
git update-ref -z --stdin <stdin &&
--
2.1.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] update-ref: fix "verify" command with missing <oldvalue>
2014-12-10 23:47 [PATCH 0/2] Fix a bug with update-ref "verify" and no oldvalue Michael Haggerty
2014-12-10 23:47 ` [PATCH 1/2] t1400: add some more tests of "update-ref --stdin"'s verify command Michael Haggerty
@ 2014-12-10 23:47 ` Michael Haggerty
2014-12-11 0:21 ` Stefan Beller
2014-12-11 16:19 ` Brad King
1 sibling, 2 replies; 7+ messages in thread
From: Michael Haggerty @ 2014-12-10 23:47 UTC (permalink / raw)
To: Junio C Hamano
Cc: Brad King, Stefan Beller, Jonathan Nieder, Ronnie Sahlberg, git,
Michael Haggerty
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>
---
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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] t1400: add some more tests of "update-ref --stdin"'s verify command
2014-12-10 23:47 ` [PATCH 1/2] t1400: add some more tests of "update-ref --stdin"'s verify command Michael Haggerty
@ 2014-12-11 0:10 ` Stefan Beller
2014-12-11 16:19 ` Brad King
1 sibling, 0 replies; 7+ messages in thread
From: Stefan Beller @ 2014-12-11 0:10 UTC (permalink / raw)
To: Michael Haggerty
Cc: Junio C Hamano, Brad King, Jonathan Nieder, Ronnie Sahlberg, git
On Thu, Dec 11, 2014 at 12:47:51AM +0100, Michael Haggerty wrote:
> Two of the tests fail because
>
> verify refs/heads/foo
>
> with no argument (not even zeros) actually *deletes* refs/heads/foo.
> This problem will be fixed in the next commit.
>
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> ---
Reviewed-By: Stefan Beller <sbeller@google.com>
> The two failing tests have to restore the $m reference when they're
> done because otherwise the bug deletes it, causing subsequent tests
> to fail.
>
> t/t1400-update-ref.sh | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 92 insertions(+)
>
> diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
> index 7b4707b..6a3cdd1 100755
> --- a/t/t1400-update-ref.sh
> +++ b/t/t1400-update-ref.sh
> @@ -619,6 +619,52 @@ test_expect_success 'stdin update/create/verify combination works' '
> test_must_fail git rev-parse --verify -q $c
> '
>
> +test_expect_success 'stdin verify succeeds for correct value' '
> + git rev-parse $m >expect &&
> + echo "verify $m $m" >stdin &&
> + git update-ref --stdin <stdin &&
> + git rev-parse $m >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_success 'stdin verify succeeds for missing reference' '
> + echo "verify refs/heads/missing $Z" >stdin &&
> + git update-ref --stdin <stdin &&
> + test_must_fail git rev-parse --verify -q refs/heads/missing
> +'
> +
> +test_expect_success 'stdin verify treats no value as missing' '
> + echo "verify refs/heads/missing" >stdin &&
> + git update-ref --stdin <stdin &&
> + test_must_fail git rev-parse --verify -q refs/heads/missing
> +'
> +
> +test_expect_success 'stdin verify fails for wrong value' '
> + git rev-parse $m >expect &&
> + echo "verify $m $m~1" >stdin &&
> + test_must_fail git update-ref --stdin <stdin &&
> + git rev-parse $m >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_success 'stdin verify fails for mistaken null value' '
> + git rev-parse $m >expect &&
> + echo "verify $m $Z" >stdin &&
> + test_must_fail git update-ref --stdin <stdin &&
> + git rev-parse $m >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_failure '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 &&
> + echo "verify $m" >stdin &&
> + test_must_fail git update-ref --stdin <stdin &&
> + git rev-parse $m >actual &&
> + test_cmp expect actual
> +'
> +
> test_expect_success 'stdin update refs works with identity updates' '
> cat >stdin <<-EOF &&
> update $a $m $m
> @@ -938,6 +984,52 @@ test_expect_success 'stdin -z update/create/verify combination works' '
> test_must_fail git rev-parse --verify -q $c
> '
>
> +test_expect_success 'stdin -z verify succeeds for correct value' '
> + git rev-parse $m >expect &&
> + printf $F "verify $m" "$m" >stdin &&
> + git update-ref -z --stdin <stdin &&
> + git rev-parse $m >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_success 'stdin -z verify succeeds for missing reference' '
> + printf $F "verify refs/heads/missing" "$Z" >stdin &&
> + git update-ref -z --stdin <stdin &&
> + test_must_fail git rev-parse --verify -q refs/heads/missing
> +'
> +
> +test_expect_success 'stdin -z verify treats no value as missing' '
> + printf $F "verify refs/heads/missing" "" >stdin &&
> + git update-ref -z --stdin <stdin &&
> + test_must_fail git rev-parse --verify -q refs/heads/missing
> +'
> +
> +test_expect_success 'stdin -z verify fails for wrong value' '
> + git rev-parse $m >expect &&
> + printf $F "verify $m" "$m~1" >stdin &&
> + test_must_fail git update-ref -z --stdin <stdin &&
> + git rev-parse $m >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_success 'stdin -z verify fails for mistaken null value' '
> + git rev-parse $m >expect &&
> + printf $F "verify $m" "$Z" >stdin &&
> + test_must_fail git update-ref -z --stdin <stdin &&
> + git rev-parse $m >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_failure '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 &&
> + printf $F "verify $m" "" >stdin &&
> + test_must_fail git update-ref -z --stdin <stdin &&
> + git rev-parse $m >actual &&
> + test_cmp expect actual
> +'
> +
> test_expect_success 'stdin -z update refs works with identity updates' '
> printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "$Z" "" >stdin &&
> git update-ref -z --stdin <stdin &&
> --
> 2.1.3
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] update-ref: fix "verify" command with missing <oldvalue>
2014-12-10 23:47 ` [PATCH 2/2] update-ref: fix "verify" command with missing <oldvalue> Michael Haggerty
@ 2014-12-11 0:21 ` Stefan Beller
2014-12-11 16:19 ` Brad King
1 sibling, 0 replies; 7+ messages in thread
From: Stefan Beller @ 2014-12-11 0:21 UTC (permalink / raw)
To: Michael Haggerty
Cc: Junio C Hamano, Brad King, Jonathan Nieder, Ronnie Sahlberg, git
On Thu, Dec 11, 2014 at 12:47:52AM +0100, Michael Haggerty wrote:
> 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>
This is reviewed by me as well.
Reviewed-by: Stefan Beller <sbeller@google.com>
> ---
> 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
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] t1400: add some more tests of "update-ref --stdin"'s verify command
2014-12-10 23:47 ` [PATCH 1/2] t1400: add some more tests of "update-ref --stdin"'s verify command Michael Haggerty
2014-12-11 0:10 ` Stefan Beller
@ 2014-12-11 16:19 ` Brad King
1 sibling, 0 replies; 7+ messages in thread
From: Brad King @ 2014-12-11 16:19 UTC (permalink / raw)
To: Michael Haggerty
Cc: Junio C Hamano, Stefan Beller, Jonathan Nieder, Ronnie Sahlberg,
git
On 12/10/2014 6:47 PM, Michael Haggerty wrote:
> Two of the tests fail because
>
> verify refs/heads/foo
>
> with no argument (not even zeros) actually *deletes* refs/heads/foo.
> This problem will be fixed in the next commit.
Reviewed-by: Brad King <brad.king@kitware.com>
-Brad
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] update-ref: fix "verify" command with missing <oldvalue>
2014-12-10 23:47 ` [PATCH 2/2] update-ref: fix "verify" command with missing <oldvalue> Michael Haggerty
2014-12-11 0:21 ` Stefan Beller
@ 2014-12-11 16:19 ` Brad King
1 sibling, 0 replies; 7+ messages in thread
From: Brad King @ 2014-12-11 16:19 UTC (permalink / raw)
To: Michael Haggerty
Cc: Junio C Hamano, Stefan Beller, Jonathan Nieder, Ronnie Sahlberg,
git
On 12/10/2014 6:47 PM, Michael Haggerty wrote:
> set have_old unconditionally and set old_sha1 to null_sha1.
Reviewed-by: Brad King <brad.king@kitware.com>
-Brad
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-12-11 16:19 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-10 23:47 [PATCH 0/2] Fix a bug with update-ref "verify" and no oldvalue Michael Haggerty
2014-12-10 23:47 ` [PATCH 1/2] t1400: add some more tests of "update-ref --stdin"'s verify command Michael Haggerty
2014-12-11 0:10 ` Stefan Beller
2014-12-11 16:19 ` Brad King
2014-12-10 23:47 ` [PATCH 2/2] update-ref: fix "verify" command with missing <oldvalue> Michael Haggerty
2014-12-11 0:21 ` Stefan Beller
2014-12-11 16:19 ` Brad King
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).