* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Mikael Magnusson @ 2011-10-20 9:38 UTC (permalink / raw)
To: Jeff King; +Cc: Ævar Arnfjörð, Git Mailing List
In-Reply-To: <20111019190114.GA4670@sigill.intra.peff.net>
On 19 October 2011 21:01, Jeff King <peff@peff.net> wrote:
> On Wed, Oct 19, 2011 at 08:03:24PM +0200, Ævar Arnfjörð Bjarmason wrote:
>
>> This is quick hack I wrote just before leaving work to show that I
>> could indeed push patches to our main repository starting with
>> 31337. Names hidden to protect the innocent.
>
> Clever and amusing.
>
>> Which in just over a minute will generate, in my case:
>>
>> $ git show --pretty=raw 313375d995e6f8b7773c6ed1ee165e5a9e15690b | head -n 7
>> commit 313375d995e6f8b7773c6ed1ee165e5a9e15690b
>> tree c9bebc99c05dfe61cccf02ebdf442945c8ff8b3c
>> parent 0dce2d45a79d26a593f0e12301cdfeb7eb23c17a
>> author Ævar Arnfjörð Bjarmason <avar@example.com> <censored> <censored>
>> committer Ævar Arnfjörð Bjarmason <avar@example.com> <censored> <censored>
>> lulz 697889
>
> Nice header name.
If you don't mind waiting, you could just increase the timestamps
until you get the desired collision. (If you still want them to be
correct, trying 4000000 times would about 6 weeks though :).
--
Mikael Magnusson
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Nguyen Thai Ngoc Duy @ 2011-10-20 9:14 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, Ævar Arnfjörð, Git Mailing List
In-Reply-To: <7vvcrk9td7.fsf@alter.siamese.dyndns.org>
On Thu, Oct 20, 2011 at 3:31 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
>
>> And nothing shows up in the body, because git truncates at the NUL we
>> added:
>>
>> $ git show
>> commit 31337a1093af2d97eb2e6c08b261c2946395fdd3
>> Author: Jeff King <peff@peff.net>
>> Date: Wed Oct 19 15:34:00 2011 -0400
>>
>> 10
>>
>> diff --git a/file b/file
>
> But you cannot hide from "cat-file commit" ;-)
>
> With the recent push to more (perceived) security, it may probably make
> sense to teach "log" family commands to quote-show ^@ and what is behind
> in their output by default, perhaps with an option to turn it off.
What about NUL in file name in tree objects? Suppose the original tree
has an entry named "goodthing". With luck, they might be able to
create a new tree object with the entry renamed to "evil\x001234" that
has the same SHA-1. Could that possibly cause any problems?
--
Duy
^ permalink raw reply
* Re: [PATCH 3/6] revert: fix buffer overflow in insn sheet parser
From: Jonathan Nieder @ 2011-10-20 9:09 UTC (permalink / raw)
To: Ramkumar Ramachandra; +Cc: Junio C Hamano, Git List, Christian Couder
In-Reply-To: <4E9FE061.3080601@gmail.com>
Ramkumar Ramachandra wrote:
> Okay. How about putting this after 5/6?
>
> -- 8< --
> Subject: [PATCH] t3510: guard against buffer overflows in parser
>
> To guard against a buffer overflow in the parser, verify that
> instruction sheets with overly long object names are parsed.
Looks good, except I would explain it differently, to avoid referring
to hypothetical implementation details ("What buffer overflow?"):
test: git cherry-pick --continue should cope with long object names
A naive implementation that uses a commit-id-shaped buffer
to store the word after "pick" in .git/sequencer/todo lines
would crash often. Our implementation is not so naive, but
add a test anyway to futureproof it.
Or:
test: make sure the "cherry-pick --continue" buffer overflow doesn't come back
Before commit ..., "git cherry-pick --continue" would overflow
under ... circumstance. Add a test to make sure it doesn't
happen again.
Though the implementation is actually better than that --- it can even
cope with a valid object name (e.g., a long name of a branch, or
something like "HEAD^{/refs.c: ensure struct whose member}") that is
that long, without truncating it. So if you have time for it, I think
it would be worth a test where the "git cherry-pick --continue"
succeeds, too.
Thanks,
Jonathan
^ permalink raw reply
* Re: [PATCH 3/6] revert: fix buffer overflow in insn sheet parser
From: Ramkumar Ramachandra @ 2011-10-20 8:48 UTC (permalink / raw)
To: Jonathan Nieder, Junio C Hamano; +Cc: Git List, Christian Couder
In-Reply-To: <20111020080328.GA12337@elie.hsd1.il.comcast.net>
Hi Jonathan and Junio,
Jonathan Nieder writes:
> Junio C Hamano wrote:
>> Ramkumar Ramachandra <artagnon@gmail.com> writes:
>
>>> Check that the commit name argument to a "pick" or "revert" action in
>>> '.git/sequencer/todo' is not too long
> [...]
>> Given that this function is going to be fixed properly so that it does not
>> even need to use the "on-stack buffer", is this really necessary?
>
> Right, I don't think it is. Keeping a testcase sounds worthwhile,
> though.
Okay. How about putting this after 5/6?
-- 8< --
Subject: [PATCH] t3510: guard against buffer overflows in parser
To guard against a buffer overflow in the parser, verify that
instruction sheets with overly long object names are parsed.
Suggested-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
t/t3510-cherry-pick-sequence.sh | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index 0e29e03..39b55c1 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -12,6 +12,9 @@ test_description='Test cherry-pick continuation features
. ./test-lib.sh
+# Repeat first match 10 times
+_r10='\1\1\1\1\1\1\1\1\1\1'
+
pristine_detach () {
git cherry-pick --reset &&
git checkout -f "$1^0" &&
@@ -211,6 +214,17 @@ test_expect_success 'malformed instruction sheet 2' '
test_must_fail git cherry-pick --continue
'
+test_expect_success 'malformed instruction sheet 3' '
+ pristine_detach initial &&
+ test_must_fail git cherry-pick base..anotherpick &&
+ echo "resolved" >foo &&
+ git add foo &&
+ git commit &&
+ sed "s/pick \([0-9a-f]*\)/pick $_r10/" .git/sequencer/todo >new_sheet &&
+ cp new_sheet .git/sequencer/todo &&
+ test_must_fail git cherry-pick --continue
+'
+
test_expect_success 'commit descriptions in insn sheet are optional' '
pristine_detach initial &&
test_must_fail git cherry-pick base..anotherpick &&
--
1.7.6.351.gb35ac.dirty
^ permalink raw reply related
* Re: [PATCH 3/6] revert: fix buffer overflow in insn sheet parser
From: Jonathan Nieder @ 2011-10-20 8:03 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Ramkumar Ramachandra, Git List, Christian Couder
In-Reply-To: <7v8vogbgai.fsf@alter.siamese.dyndns.org>
Junio C Hamano wrote:
> Ramkumar Ramachandra <artagnon@gmail.com> writes:
>> Check that the commit name argument to a "pick" or "revert" action in
>> '.git/sequencer/todo' is not too long
[...]
> Given that this function is going to be fixed properly so that it does not
> even need to use the "on-stack buffer", is this really necessary?
Right, I don't think it is. Keeping a testcase sounds worthwhile,
though.
^ permalink raw reply
* Re: [PATCH 12/12] is_refname_available(): reimplement using do_for_each_ref_in_array()
From: Michael Haggerty @ 2011-10-20 7:46 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips
In-Reply-To: <7v4nz4bftk.fsf@alter.siamese.dyndns.org>
On 10/20/2011 03:40 AM, Junio C Hamano wrote:
> Hmm, why is this patch and only this one in the series full of whitespace
> violations? Did you use a different settings or something?
This happens rarely; I don't know why. Maybe I copy-pasted snippets
from a view in an application that expanded the tabs. Maybe emacs's
eliza program has achieved self-awareness and is punishing me for never
having properly learned elisp.
The incorrect lines are indented with 7, not 8, spaces so "tabify"
didn't help either.
I'll fix in reroll after I've received any other feedback.
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply
* Re: [PATCH 08/12] do_for_each_ref_in_arrays(): new function
From: Michael Haggerty @ 2011-10-20 7:29 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips
In-Reply-To: <7vfwiobo75.fsf@alter.siamese.dyndns.org>
On 10/20/2011 12:39 AM, Junio C Hamano wrote:
> Is this necessary? IOW, is the helper function usable in any context
> other than merge-iterate loose and packed refs?
Soon the packed and cached refs will each be stored hierarchically, so
iteration through the combined caches will use a call to
do_for_each_ref_in_arrays() in each subdirectory, recursively.
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Nguyen Thai Ngoc Duy @ 2011-10-20 7:27 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, Ævar Arnfjörð, Git Mailing List
In-Reply-To: <7vr5289mlu.fsf@alter.siamese.dyndns.org>
On Thu, Oct 20, 2011 at 5:57 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
>
>> Agreed. Having hidden cruft makes birthday collision attacks easier (or
>> it will, if sha1 ever gets broken to that point). Unfortunately, there
>> is a _ton_ of code which assumes that commit messages are
>> NUL-terminated, as they always have been since e871b64 (2005-05-25).
>
> I think that commit is irrelevant, as long as read_sha1_file() returns the
> contents as <ptr,len> pair, which has been the case forever. It's just the
> matter of propagating the length back up the callchain.
>
> A naïve implementation to add "len" member to struct commit would increase
> the size of the in-core commit object by sizeof(unsigned long), which we
> may want to avoid. Traversals that care nothing but the topology of the
> history would have to waste that memory and these things tend to add up
> (8-byte ulong * 250k commits = 2MB).
Or write commit_length(struct commit *c) that calculates SHA-1 from
c->buf and checks against c->object.sha1. If it does not match,
consider NUL part of the message and move to the next NUL. This
function would be expensive so we may not call frequently though.
Or store length in ((int*)c->buf)[-1].
--
Duy
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Jeff King @ 2011-10-20 7:13 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Ævar Arnfjörð Bjarmason, Git Mailing List
In-Reply-To: <7vr5289mlu.fsf@alter.siamese.dyndns.org>
On Wed, Oct 19, 2011 at 11:57:17PM -0700, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
>
> > Agreed. Having hidden cruft makes birthday collision attacks easier (or
> > it will, if sha1 ever gets broken to that point). Unfortunately, there
> > is a _ton_ of code which assumes that commit messages are
> > NUL-terminated, as they always have been since e871b64 (2005-05-25).
>
> I think that commit is irrelevant, as long as read_sha1_file() returns the
> contents as <ptr,len> pair, which has been the case forever. It's just the
> matter of propagating the length back up the callchain.
It's not that the commit is bad or the source of problems. My point is
that the assumption that commit messages are NUL-terminated has been
there for a really long time, so there are lots of spots in the code
that sloppily run string functions on them. Every one of those needs to
be found and fixed (e.g., I remember seeing this in
for-each-ref.c:find_subpos recently).
It's not impossible, of course, or even really that hard. It's just a
giant pain, and I wonder if the effort is worth it.
> A naïve implementation to add "len" member to struct commit would increase
> the size of the in-core commit object by sizeof(unsigned long), which we
> may want to avoid. Traversals that care nothing but the topology of the
> history would have to waste that memory and these things tend to add up
> (8-byte ulong * 250k commits = 2MB).
>
> Perhaps change the type of "buf" member in struct commit to a pointer to a
> <ptr,len> pair, or something? Or perhaps a few megabytes wasted between
> friends we do not care much about?
I think you'd have to convert the struct (even if not every piece of
code is converted to use it) and profile.
-Peff
^ permalink raw reply
* Re: [msysGit] Re: Compiling on Windows
From: Philip Oakley @ 2011-10-20 7:06 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Andrew Ardill, Vincent van Ravesteijn, Git MsysGit, git
In-Reply-To: <alpine.DEB.1.00.1110191816500.32316@s15462909.onlinehome-server.info>
From: "Johannes Schindelin" <Johannes.Schindelin@gmx.de>
Sent: Thursday, October 20, 2011 12:17 AM
> On Wed, 19 Oct 2011, Philip Oakley wrote:
>
>> From: "Vincent van Ravesteijn" <vfr@lyx.org>
>> > Op 18-10-2011 6:08, Andrew Ardill schreef:
>> > > Hi list, I have been searching for details on what is required to
>> > > compile on Windows, but haven't found anything conclusive. Perhaps
>> > > there is something on the wiki, but unfortunately it is down at the
>> > > moment.
>
> The quickest way to get Git for Windows compiled is to download & run
> msysGit-netinstall from http://msysgit.googlecode.com/.
>
Johannes,
I've got the msysGit-netinstall, which is excellent, however it was the
additional setting up of MSVC (Microsoft Visual Studio) that I was trying to
get going as an IDE tool - Its a tool I have to use at work so I'm familiar
with it. I know that an MSVC compilation is not perfect..., but it would
allow me easier development before a proper gcc compilation.
The C:\msysgit\git\compat\vcbuild\README gave details of the extra parts to
download but it wasn't clear to me where I should put them within the C:\ or
C:\msysgit\ directory.
The msysGit-netinstall already includes git (C:\msysgit\git), so I wasn't
sure if I should download it a second time as instructed in the README. With
the improvements in msysGit-netinstall I expect that the README is slightly
out of date for the case where the netinstall was used. The blog post gave
an indication of _where_ the downloads were to be placed, but was otherwise
very similar to the README instructions.
regards
Philip
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Junio C Hamano @ 2011-10-20 6:57 UTC (permalink / raw)
To: Jeff King; +Cc: Ævar Arnfjörð Bjarmason, Git Mailing List
In-Reply-To: <20111020043448.GA7628@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> Agreed. Having hidden cruft makes birthday collision attacks easier (or
> it will, if sha1 ever gets broken to that point). Unfortunately, there
> is a _ton_ of code which assumes that commit messages are
> NUL-terminated, as they always have been since e871b64 (2005-05-25).
I think that commit is irrelevant, as long as read_sha1_file() returns the
contents as <ptr,len> pair, which has been the case forever. It's just the
matter of propagating the length back up the callchain.
A naïve implementation to add "len" member to struct commit would increase
the size of the in-core commit object by sizeof(unsigned long), which we
may want to avoid. Traversals that care nothing but the topology of the
history would have to waste that memory and these things tend to add up
(8-byte ulong * 250k commits = 2MB).
Perhaps change the type of "buf" member in struct commit to a pointer to a
<ptr,len> pair, or something? Or perhaps a few megabytes wasted between
friends we do not care much about?
^ permalink raw reply
* Re: How to verify that lines were only moved, not edited?
From: Johannes Sixt @ 2011-10-20 6:25 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvcrkdi59.fsf@alter.siamese.dyndns.org>
Am 10/19/2011 19:07, schrieb Junio C Hamano:
> When reviewing a "supposedly move-only" change, I typically just grab +/-
> blocks from the patch, remove the +/- prefix and run comparison between
> them.
Thanks. As I explained to Jeff, I don't have a block-move, but the sort
order of a block of lines was changed "in place". It seems I have to fall
back to a similarly manual method as well (e.g., compare the
whole-file-sorted versions of the pre- and the post-image).
-- Hannes
^ permalink raw reply
* Re: How to verify that lines were only moved, not edited?
From: Johannes Sixt @ 2011-10-20 6:20 UTC (permalink / raw)
To: Jeff King; +Cc: git
In-Reply-To: <20111019163354.GB3157@sigill.intra.peff.net>
Am 10/19/2011 18:33, schrieb Jeff King:
> git init
> seq 1 5000 >foo
> git add foo
> git commit -m initial
> sed -i '/^2..$/d' foo
> seq 200 299 >>foo
> git commit -a -m 'move 200-299 to end'
>
> I get the expected result from "git blame -M" (i.e., everything
> attributed to the root commit).
I see. My example is more like this:
for i in `seq 1 20`; do md5sum - <<< $i; done > foo
git commit -a -m foo
for i in `seq 1 20`; do md5sum - <<< $i; done | sort > foo
git commit -a -m foo\ sorted
i.e., the sort order of a block of lines was changed "in place". Here,
most of the lines are attributed to the last commit. Am I expecting too
much from git-blame to detect line motions in such a case?
-- Hannes
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Jeff King @ 2011-10-20 4:34 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Ævar Arnfjörð Bjarmason, Git Mailing List
In-Reply-To: <7vvcrk9td7.fsf@alter.siamese.dyndns.org>
On Wed, Oct 19, 2011 at 09:31:16PM -0700, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
>
> > And nothing shows up in the body, because git truncates at the NUL we
> > added:
> >
> > $ git show
> > commit 31337a1093af2d97eb2e6c08b261c2946395fdd3
> > Author: Jeff King <peff@peff.net>
> > Date: Wed Oct 19 15:34:00 2011 -0400
> >
> > 10
> >
> > diff --git a/file b/file
>
> But you cannot hide from "cat-file commit" ;-)
Yes. The implementation is a horrible hack, second only in grossness to
the original idea. :)
> With the recent push to more (perceived) security, it may probably make
> sense to teach "log" family commands to quote-show ^@ and what is behind
> in their output by default, perhaps with an option to turn it off.
Agreed. Having hidden cruft makes birthday collision attacks easier (or
it will, if sha1 ever gets broken to that point). Unfortunately, there
is a _ton_ of code which assumes that commit messages are
NUL-terminated, as they always have been since e871b64 (2005-05-25).
-Peff
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Kyle Moffett @ 2011-10-20 4:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, Ævar Arnfjörð, Git Mailing List
In-Reply-To: <7vzkgw9tjw.fsf@alter.siamese.dyndns.org>
On Thu, Oct 20, 2011 at 00:27, Junio C Hamano <gitster@pobox.com> wrote:
> Kyle Moffett <kyle@moffetthome.net> writes:
>
>> Heh, there's one other practical downside I can think of...
>>
>> If you create a bunch of commits with the same 8-hex-character prefix
>> then suddenly the "git describe" logic for using the first 7 commit ID
>> characters gets a whole lot less useful.
>
> In the sense that you need to cut and paste a lot more characters, you are
> correct that it would make it less useful, but if you are talking about
> uniqueness, you are mistaken.
>
> The rule is not "using the first 7 hexdigits", but is "using as many
> hexdigits to make assure uniqueness, but use at least 7".
Well, yes, but if you generate some 10 commits with the same
7-character prefix, run "git describe", and then generate another
several with the same prefix... Chances are the previously-unique
output of "git describe" is no longer unique.
Also, even if you do use enough characters for it to be reliably
unique, it's not really an abbreviation if your commit description is
"v2.0.3-42-gdeadbeef04a69f", with that many characters you might as
well just paste the whole SHA1 sum.
With all that said, it is a very clever (and ugly) hack :-D. Kudos!
Cheers,
Kyle Moffett
--
Curious about my work on the Debian powerpcspe port?
I'm keeping a blog here: http://pureperl.blogspot.com/
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Junio C Hamano @ 2011-10-20 4:31 UTC (permalink / raw)
To: Jeff King; +Cc: Ævar Arnfjörð Bjarmason, Git Mailing List
In-Reply-To: <20111019193834.GA14168@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> And nothing shows up in the body, because git truncates at the NUL we
> added:
>
> $ git show
> commit 31337a1093af2d97eb2e6c08b261c2946395fdd3
> Author: Jeff King <peff@peff.net>
> Date: Wed Oct 19 15:34:00 2011 -0400
>
> 10
>
> diff --git a/file b/file
But you cannot hide from "cat-file commit" ;-)
With the recent push to more (perceived) security, it may probably make
sense to teach "log" family commands to quote-show ^@ and what is behind
in their output by default, perhaps with an option to turn it off.
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Junio C Hamano @ 2011-10-20 4:27 UTC (permalink / raw)
To: Kyle Moffett; +Cc: Jeff King, Ævar Arnfjörð, Git Mailing List
In-Reply-To: <CAGZ=bqK2oVPxW3mm-WHMd1+KSiPquympJyhRqLWr1F=G74p+BA@mail.gmail.com>
Kyle Moffett <kyle@moffetthome.net> writes:
> Heh, there's one other practical downside I can think of...
>
> If you create a bunch of commits with the same 8-hex-character prefix
> then suddenly the "git describe" logic for using the first 7 commit ID
> characters gets a whole lot less useful.
In the sense that you need to cut and paste a lot more characters, you are
correct that it would make it less useful, but if you are talking about
uniqueness, you are mistaken.
The rule is not "using the first 7 hexdigits", but is "using as many
hexdigits to make assure uniqueness, but use at least 7".
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Jeff King @ 2011-10-20 4:25 UTC (permalink / raw)
To: Kyle Moffett; +Cc: Ævar Arnfjörð, Git Mailing List
In-Reply-To: <CAGZ=bqK2oVPxW3mm-WHMd1+KSiPquympJyhRqLWr1F=G74p+BA@mail.gmail.com>
On Thu, Oct 20, 2011 at 12:15:03AM -0400, Kyle Moffett wrote:
> On Wed, Oct 19, 2011 at 22:51, Jeff King <peff@peff.net> wrote:
> > Keep in mind that each hex character you add increases the search space
> > by a factor of 16. deadbeef took about 70 seconds to find on my machine.
> > I'm tempted to look for "3133700..0031337", but it would probably
> > take about 4 hours.
>
> Heh, there's one other practical downside I can think of...
>
> If you create a bunch of commits with the same 8-hex-character prefix
> then suddenly the "git describe" logic for using the first 7 commit ID
> characters gets a whole lot less useful.
Actually, git will generally find a unique abbreviation among all of
your objects when using abbreviated sha1s, so you'll just get longer
abbreviations. Of course, it is only unique at the time of generation,
so new objects may make it ambiguous. Which is why the default minimum
is 7, not 1. But of course with this trick you've effectively removed
all of the entropy from those initial 7 characters, and you effectively
only have 1 or 2 non-uniform characters.
So yeah, it is worse. But really...spending millions of CPU cycles to
get a preimage collision with the partial sha1, and hack-ishly embedding
random crap after a NUL in every commit message, and _this_ is your
complaint? ;)
-Peff
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Kyle Moffett @ 2011-10-20 4:15 UTC (permalink / raw)
To: Jeff King; +Cc: Ævar Arnfjörð, Git Mailing List
In-Reply-To: <20111020025149.GA31549@sigill.intra.peff.net>
On Wed, Oct 19, 2011 at 22:51, Jeff King <peff@peff.net> wrote:
> Keep in mind that each hex character you add increases the search space
> by a factor of 16. deadbeef took about 70 seconds to find on my machine.
> I'm tempted to look for "3133700..0031337", but it would probably
> take about 4 hours.
Heh, there's one other practical downside I can think of...
If you create a bunch of commits with the same 8-hex-character prefix
then suddenly the "git describe" logic for using the first 7 commit ID
characters gets a whole lot less useful.
Cheers,
Kyle Moffett
--
Curious about my work on the Debian powerpcspe port?
I'm keeping a blog here: http://pureperl.blogspot.com/
^ permalink raw reply
* Re: [IGNORETHIS/PATCH] Choosing the sha1 prefix of your commits
From: Jeff King @ 2011-10-20 2:51 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason; +Cc: Git Mailing List
In-Reply-To: <20111019193834.GA14168@sigill.intra.peff.net>
On Wed, Oct 19, 2011 at 03:38:34PM -0400, Jeff King wrote:
> It also parameterizes the desired sha1, so you could easily find hashes
> ending in 31337, or any other pattern. Or add "git commit
> --collide=31337".
I couldn't resist:
$ git commit -q -m foo --collide=deadbeef &&
git rev-list -1 HEAD
deadbeefdbd6e62a2185606a4fad653e22509b56
You can also do:
$ SHA1=0000000000000000000000000000000000031337
$ MASK=00000000000000000000000000000000000fffff
$ git commit -q -m foo --collide=$SHA1/$MASK &&
git rev-list -1 HEAD
ea49af84db92ed0d2bc3ed13810f5990e7c31337
Keep in mind that each hex character you add increases the search space
by a factor of 16. deadbeef took about 70 seconds to find on my machine.
I'm tempted to look for "3133700..0031337", but it would probably
take about 4 hours.
Patch is below.
-Peff
---
diff --git a/builtin/commit.c b/builtin/commit.c
index c46f2d1..734a7ab 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -105,6 +105,10 @@
static const char *only_include_assumed;
static struct strbuf message;
+static int collide;
+static unsigned char collide_sha1[20];
+static unsigned char collide_mask[20];
+
static int null_termination;
static enum {
STATUS_FORMAT_LONG,
@@ -125,6 +129,52 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset)
return 0;
}
+static int parse_partial_sha1(const char *s, unsigned char sha1[20])
+{
+ unsigned int i;
+
+ hashclr(sha1);
+
+ for (i = 0; i < 40 && s[i]; i++) {
+ unsigned int v = hexval(s[i]);
+ if (v & ~0xf)
+ break;
+ if (!(i & 1))
+ v <<= 4;
+ sha1[i/2] |= v;
+ }
+ return i;
+}
+
+static void fill_sha1_mask(int n, unsigned char mask[20]) {
+ int i;
+
+ hashclr(mask);
+ for (i = 0; i < n/2; i++)
+ mask[i] = 0xff;
+ if (n & 1)
+ mask[i] = 0xf0;
+}
+
+static int opt_parse_collide(const struct option *opt, const char *arg,
+ int unset)
+{
+ if (unset)
+ collide = 0;
+ else {
+ int n = parse_partial_sha1(arg, collide_sha1);
+ if (!arg[n])
+ fill_sha1_mask(n, collide_mask);
+ else if (arg[n] == '/')
+ parse_partial_sha1(arg + n + 1, collide_mask);
+ else
+ die("invalid --collide sha1: %s", arg);
+ collide = 1;
+ }
+ return 0;
+}
+
+
static struct option builtin_commit_options[] = {
OPT__QUIET(&quiet, "suppress summary after successful commit"),
OPT__VERBOSE(&verbose, "show diff in commit message template"),
@@ -144,6 +194,7 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset)
OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
OPT_BOOLEAN(0, "status", &include_status, "include status in commit message template"),
+ OPT_CALLBACK(0, "collide", NULL, "sha1[/mask]", "choose commit sha1 like <sha1>", opt_parse_collide),
/* end commit message options */
OPT_GROUP("Commit contents options"),
@@ -1483,8 +1534,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
exit(1);
}
- if (commit_tree(sb.buf, active_cache_tree->sha1, parents, sha1,
- author_ident.buf)) {
+ if (commit_tree_collide(sb.buf, active_cache_tree->sha1, parents, sha1,
+ author_ident.buf,
+ collide ? collide_sha1 : NULL, collide_mask)) {
rollback_index_files();
die(_("failed to write commit object"));
}
diff --git a/commit.c b/commit.c
index 73b7e00..24ddccd 100644
--- a/commit.c
+++ b/commit.c
@@ -840,6 +840,54 @@ struct commit_list *reduce_heads(struct commit_list *heads)
return result;
}
+static inline int sha1_match_mask(const unsigned char *sha1,
+ const unsigned char *want,
+ const unsigned char *mask)
+{
+ int i;
+ for (i = 0; i < 20; i++)
+ if ((want[i] & mask[i]) != (sha1[i] & mask[i]))
+ return 0;
+ return 1;
+}
+
+static void collide_commit(struct strbuf *data,
+ const unsigned char *want,
+ const unsigned char *mask)
+{
+ static const char terminator[] = { 0 };
+ char header[32];
+ int header_len;
+ unsigned int lulz;
+ SHA_CTX base;
+
+ header_len = snprintf(header, sizeof(header),
+ "commit %lu",
+ data->len + 1 + sizeof(lulz)) + 1;
+ SHA1_Init(&base);
+ SHA1_Update(&base, header, header_len);
+ SHA1_Update(&base, data->buf, data->len);
+ SHA1_Update(&base, terminator, sizeof(terminator));
+
+ lulz = 0;
+ do {
+ SHA_CTX guess;
+ unsigned char sha1[20];
+
+ memcpy(&guess, &base, sizeof(guess));
+ SHA1_Update(&guess, &lulz, sizeof(lulz));
+ SHA1_Final(sha1, &guess);
+
+ if (sha1_match_mask(sha1, want, mask)) {
+ strbuf_add(data, terminator, sizeof(terminator));
+ strbuf_add(data, &lulz, sizeof(lulz));
+ return;
+ }
+
+ lulz++;
+ } while (1);
+}
+
static const char commit_utf8_warn[] =
"Warning: commit message does not conform to UTF-8.\n"
"You may want to amend it after fixing the message, or set the config\n"
@@ -849,6 +897,15 @@ int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret,
const char *author)
{
+ return commit_tree_collide(msg, tree, parents, ret, author,
+ NULL, NULL);
+}
+
+int commit_tree_collide(const char *msg, unsigned char *tree,
+ struct commit_list *parents, unsigned char *ret,
+ const char *author, const unsigned char *want,
+ const unsigned char *mask)
+{
int result;
int encoding_is_utf8;
struct strbuf buffer;
@@ -890,6 +947,9 @@ int commit_tree(const char *msg, unsigned char *tree,
if (encoding_is_utf8 && !is_utf8(buffer.buf))
fprintf(stderr, commit_utf8_warn);
+ if (want && mask)
+ collide_commit(&buffer, want, mask);
+
result = write_sha1_file(buffer.buf, buffer.len, commit_type, ret);
strbuf_release(&buffer);
return result;
diff --git a/commit.h b/commit.h
index 009b113..337dcbd 100644
--- a/commit.h
+++ b/commit.h
@@ -184,5 +184,9 @@ static inline int single_parent(struct commit *commit)
extern int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret,
const char *author);
+extern int commit_tree_collide(const char *msg, unsigned char *tree,
+ struct commit_list *parents, unsigned char *ret,
+ const char *author, const unsigned char *sha1,
+ const unsigned char *mask);
#endif /* COMMIT_H */
^ permalink raw reply related
* Re: [PATCH 12/12] is_refname_available(): reimplement using do_for_each_ref_in_array()
From: Junio C Hamano @ 2011-10-20 1:40 UTC (permalink / raw)
To: mhagger
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips
In-Reply-To: <1319060692-27216-13-git-send-email-mhagger@alum.mit.edu>
Hmm, why is this patch and only this one in the series full of whitespace
violations? Did you use a different settings or something?
^ permalink raw reply
* Re: [PATCH 3/6] revert: fix buffer overflow in insn sheet parser
From: Junio C Hamano @ 2011-10-20 1:30 UTC (permalink / raw)
To: Ramkumar Ramachandra; +Cc: Git List, Jonathan Nieder, Christian Couder
In-Reply-To: <1319058208-17923-4-git-send-email-artagnon@gmail.com>
Ramkumar Ramachandra <artagnon@gmail.com> writes:
> Check that the commit name argument to a "pick" or "revert" action in
> '.git/sequencer/todo' is not too long, to avoid overflowing an
> on-stack buffer. This fixes a regression introduced by 5a5d80f4
> (revert: Introduce --continue to continue the operation, 2011-08-04).
Given that this function is going to be fixed properly so that it does not
even need to use the "on-stack buffer", is this really necessary?
^ permalink raw reply
* Re: git-p4.skipSubmitEdit
From: Pete Wyckoff @ 2011-10-20 1:16 UTC (permalink / raw)
To: Luke Diamand; +Cc: L. A. Linden Levy, git
In-Reply-To: <4E9DBD0B.7020505@diamand.org>
luke@diamand.org wrote on Tue, 18 Oct 2011 18:53 +0100:
> Looks good, one minor nit (see below) and a comment.
[..]
> >+ # invoke the editor
> >+ if os.environ.has_key("P4EDITOR"):
> >+ editor = os.environ.get("P4EDITOR")
> >+ else:
> >+ editor = read_pipe("git var GIT_EDITOR").strip()
> >+ system(editor + " " + template_file)
>
> This is where we should really check the return code. However, doing
> so seems to break lots of the existing tests so it's not as easy as
> it looks.
Indeed. I'll not fix that now, but agree it should be.
> >+
> >+ # If the file was not saved, prompt to see if this patch should
> >+ # be skipped. But skip this verification step if configured so.
> >+ if gitConfig("git-p4.skipSubmitEditCheck") == "true":
> >+ print "return true for skipSubmitEditCheck"
>
> You print a helpful/annoying(?) message here, but not further up at
> skipSubmitEdit?
Aargh. Leaked debug code. Thanks for noticing. I got rid of
it.
-- Pete
^ permalink raw reply
* [PATCH v4 2/5] commit: teach --gpg-sign option
From: Junio C Hamano @ 2011-10-20 0:37 UTC (permalink / raw)
To: git
In-Reply-To: <1319071023-31919-1-git-send-email-gitster@pobox.com>
And this uses the gpg-interface.[ch] to allow signing the commit, i.e.
$ git commit --gpg-sign -m foo
You need a passphrase to unlock the secret key for
user: "Junio C Hamano <gitster@pobox.com>"
4096-bit RSA key, ID 96AFE6CB, created 2011-10-03 (main key ID 713660A7)
[master 8457d13] foo
1 files changed, 1 insertions(+), 0 deletions(-)
The lines of GPG detached signature are placed in new header lines, after
the standard tree/parent/author/committer headers, instead of tucking the
signature block at the end of the commit log message text (similar to how
signed tag is done), for multiple reasons:
- The signature won't clutter output from "git log" and friends if it is
in the extra header. If we place it at the end of the log message, we
would need to teach "git log" and friends to strip the signature block
with an option.
- Teaching new versions of "git log" and "gitk" to optionally verify and
show signatures is cleaner if we structurally know where the signature
block is (instead of scanning in the commit log message).
- The signature needs to be stripped upon various commit rewriting
operations, e.g. rebase, filter-branch, etc. They all already ignore
unknown headers, but if we place signature in the log message, all of
these tools (and third-party tools) also need to learn how a signature
block would look like.
- When we added the optional encoding header, all the tools (both in tree
and third-party) that acts on the raw commit object should have been
fixed to ignore headers they do not understand, so it is not like that
new header would be more likely to break than extra text in the commit.
A commit made with the above sample sequence would look like this:
$ git cat-file commit HEAD
tree 3cd71d90e3db4136e5260ab54599791c4f883b9d
parent b87755351a47b09cb27d6913e6e0e17e6254a4d4
author Junio C Hamano <gitster@pobox.com> 1317862251 -0700
committer Junio C Hamano <gitster@pobox.com> 1317862251 -0700
gpgsig -----BEGIN PGP SIGNATURE-----
gpgsig Version: GnuPG v1.4.10 (GNU/Linux)
gpgsig
gpgsig iQIcBAABAgAGBQJOjPtrAAoJELC16IaWr+bL4TMP/RSe2Y/jYnCkds9unO5JEnfG
gpgsig ...
gpgsig =dt98
gpgsig -----END PGP SIGNATURE-----
foo
but "git log" (unless you ask for it with --pretty=raw) output is not
cluttered with the signature information.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/commit-tree.c | 24 +++++++++++++++++++++---
builtin/commit.c | 12 ++++++++++--
builtin/merge.c | 16 ++++++++++++++--
commit.c | 40 +++++++++++++++++++++++++++++++++++++++-
commit.h | 2 +-
notes-cache.c | 2 +-
notes-merge.c | 2 +-
7 files changed, 87 insertions(+), 11 deletions(-)
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index d083795..a17811f 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -8,8 +8,9 @@
#include "tree.h"
#include "builtin.h"
#include "utf8.h"
+#include "gpg-interface.h"
-static const char commit_tree_usage[] = "git commit-tree <sha1> [(-p <sha1>)...] < changelog";
+static const char commit_tree_usage[] = "git commit-tree [-S<signer>] <sha1> [(-p <sha1>)...] < changelog";
static void new_parent(struct commit *parent, struct commit_list **parents_p)
{
@@ -25,6 +26,14 @@ static void new_parent(struct commit *parent, struct commit_list **parents_p)
commit_list_insert(parent, parents_p);
}
+static int commit_tree_config(const char *var, const char *value, void *cb)
+{
+ int status = git_gpg_config(var, value, NULL);
+ if (status)
+ return status;
+ return git_default_config(var, value, cb);
+}
+
int cmd_commit_tree(int argc, const char **argv, const char *prefix)
{
int i;
@@ -32,11 +41,19 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
unsigned char tree_sha1[20];
unsigned char commit_sha1[20];
struct strbuf buffer = STRBUF_INIT;
+ const char *sign_commit = NULL;
- git_config(git_default_config, NULL);
+ git_config(commit_tree_config, NULL);
if (argc < 2 || !strcmp(argv[1], "-h"))
usage(commit_tree_usage);
+
+ if (!memcmp(argv[1], "-S", 2)) {
+ sign_commit = argv[1] + 2;
+ argv++;
+ argc--;
+ }
+
if (get_sha1(argv[1], tree_sha1))
die("Not a valid object name %s", argv[1]);
@@ -56,7 +73,8 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
if (strbuf_read(&buffer, 0, 0) < 0)
die_errno("git commit-tree: failed to read");
- if (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) {
+ if (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1,
+ NULL, sign_commit)) {
strbuf_release(&buffer);
return 1;
}
diff --git a/builtin/commit.c b/builtin/commit.c
index cbc9613..90cf7e8 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -26,6 +26,7 @@
#include "unpack-trees.h"
#include "quote.h"
#include "submodule.h"
+#include "gpg-interface.h"
static const char * const builtin_commit_usage[] = {
"git commit [options] [--] <filepattern>...",
@@ -85,6 +86,8 @@ static int all, edit_flag, also, interactive, patch_interactive, only, amend, si
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
static int no_post_rewrite, allow_empty_message;
static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
+static char *sign_commit;
+
/*
* The default commit message cleanup mode will remove the lines
* beginning with # (shell comments) and leading and trailing
@@ -144,6 +147,8 @@ static struct option builtin_commit_options[] = {
OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
OPT_BOOLEAN(0, "status", &include_status, "include status in commit message template"),
+ { OPTION_STRING, 'S', "gpg-sign", &sign_commit, "key id",
+ "GPG sign commit", PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
/* end commit message options */
OPT_GROUP("Commit contents options"),
@@ -1323,6 +1328,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1,
static int git_commit_config(const char *k, const char *v, void *cb)
{
struct wt_status *s = cb;
+ int status;
if (!strcmp(k, "commit.template"))
return git_config_pathname(&template_file, k, v);
@@ -1330,7 +1336,9 @@ static int git_commit_config(const char *k, const char *v, void *cb)
include_status = git_config_bool(k, v);
return 0;
}
-
+ status = git_gpg_config(k, v, NULL);
+ if (status)
+ return status;
return git_status_config(k, v, s);
}
@@ -1481,7 +1489,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
}
if (commit_tree(sb.buf, active_cache_tree->sha1, parents, sha1,
- author_ident.buf)) {
+ author_ident.buf, sign_commit)) {
rollback_index_files();
die(_("failed to write commit object"));
}
diff --git a/builtin/merge.c b/builtin/merge.c
index ab4077f..53cff02 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -26,6 +26,7 @@
#include "merge-recursive.h"
#include "resolve-undo.h"
#include "remote.h"
+#include "gpg-interface.h"
#define DEFAULT_TWOHEAD (1<<0)
#define DEFAULT_OCTOPUS (1<<1)
@@ -63,6 +64,7 @@ static int allow_rerere_auto;
static int abort_current_merge;
static int show_progress = -1;
static int default_to_upstream;
+static const char *sign_commit;
static struct strategy all_strategy[] = {
{ "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -206,6 +208,8 @@ static struct option builtin_merge_options[] = {
OPT_BOOLEAN(0, "abort", &abort_current_merge,
"abort the current in-progress merge"),
OPT_SET_INT(0, "progress", &show_progress, "force progress reporting", 1),
+ { OPTION_STRING, 'S', "gpg-sign", &sign_commit, "key id",
+ "GPG sign commit", PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
OPT_END()
};
@@ -525,6 +529,8 @@ static void parse_branch_merge_options(char *bmo)
static int git_merge_config(const char *k, const char *v, void *cb)
{
+ int status;
+
if (branch && !prefixcmp(k, "branch.") &&
!prefixcmp(k + 7, branch) &&
!strcmp(k + 7 + strlen(branch), ".mergeoptions")) {
@@ -562,6 +568,10 @@ static int git_merge_config(const char *k, const char *v, void *cb)
default_to_upstream = git_config_bool(k, v);
return 0;
}
+
+ status = git_gpg_config(k, v, NULL);
+ if (status)
+ return status;
return git_diff_ui_config(k, v, cb);
}
@@ -870,7 +880,8 @@ static int merge_trivial(void)
parent->next->item = remoteheads->item;
parent->next->next = NULL;
run_prepare_commit_msg();
- commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
+ commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL,
+ sign_commit);
finish(result_commit, "In-index merge");
drop_save();
return 0;
@@ -900,7 +911,8 @@ static int finish_automerge(struct commit_list *common,
free_commit_list(remoteheads);
strbuf_addch(&merge_msg, '\n');
run_prepare_commit_msg();
- commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
+ commit_tree(merge_msg.buf, result_tree, parents, result_commit,
+ NULL, sign_commit);
strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
finish(result_commit, buf.buf);
strbuf_release(&buf);
diff --git a/commit.c b/commit.c
index 97b4327..4bff3cd 100644
--- a/commit.c
+++ b/commit.c
@@ -6,6 +6,7 @@
#include "diff.h"
#include "revision.h"
#include "notes.h"
+#include "gpg-interface.h"
int save_commit_buffer = 1;
@@ -814,6 +815,40 @@ struct commit_list *reduce_heads(struct commit_list *heads)
return result;
}
+static const char gpg_sig_header[] = "gpgsig ";
+static const int gpg_sig_header_len = sizeof(gpg_sig_header) - 1;
+
+static int do_sign_commit(struct strbuf *buf, const char *keyid)
+{
+ struct strbuf sig = STRBUF_INIT;
+ int inspos, copypos;
+
+ /* find the end of the header */
+ inspos = strstr(buf->buf, "\n\n") - buf->buf + 1;
+
+ if (!keyid || !*keyid)
+ keyid = get_signing_key();
+ if (sign_buffer(buf, &sig, keyid)) {
+ strbuf_release(&sig);
+ return -1;
+ }
+
+ for (copypos = 0; sig.buf[copypos]; ) {
+ const char *bol = sig.buf + copypos;
+ const char *eol = strchrnul(bol, '\n');
+ int len = (eol - bol) + !!*eol;
+
+ strbuf_insert(buf, inspos, gpg_sig_header, gpg_sig_header_len);
+ inspos += gpg_sig_header_len;
+ strbuf_insert(buf, inspos, bol, len);
+ inspos += len;
+ copypos += len;
+ }
+ strbuf_release(&sig);
+ return 0;
+}
+
+
static const char commit_utf8_warn[] =
"Warning: commit message does not conform to UTF-8.\n"
"You may want to amend it after fixing the message, or set the config\n"
@@ -821,7 +856,7 @@ static const char commit_utf8_warn[] =
int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret,
- const char *author)
+ const char *author, const char *sign_commit)
{
int result;
int encoding_is_utf8;
@@ -864,6 +899,9 @@ int commit_tree(const char *msg, unsigned char *tree,
if (encoding_is_utf8 && !is_utf8(buffer.buf))
fprintf(stderr, commit_utf8_warn);
+ if (sign_commit && do_sign_commit(&buffer, sign_commit))
+ return -1;
+
result = write_sha1_file(buffer.buf, buffer.len, commit_type, ret);
strbuf_release(&buffer);
return result;
diff --git a/commit.h b/commit.h
index 12d100b8..8c2419b 100644
--- a/commit.h
+++ b/commit.h
@@ -175,6 +175,6 @@ struct commit_list *reduce_heads(struct commit_list *heads);
extern int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret,
- const char *author);
+ const char *author, const char *sign_commit);
#endif /* COMMIT_H */
diff --git a/notes-cache.c b/notes-cache.c
index 4c8984e..c36a960 100644
--- a/notes-cache.c
+++ b/notes-cache.c
@@ -56,7 +56,7 @@ int notes_cache_write(struct notes_cache *c)
if (write_notes_tree(&c->tree, tree_sha1))
return -1;
- if (commit_tree(c->validity, tree_sha1, NULL, commit_sha1, NULL) < 0)
+ if (commit_tree(c->validity, tree_sha1, NULL, commit_sha1, NULL, NULL) < 0)
return -1;
if (update_ref("update notes cache", c->tree.ref, commit_sha1, NULL,
0, QUIET_ON_ERR) < 0)
diff --git a/notes-merge.c b/notes-merge.c
index e1aaf43..c29c434 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -546,7 +546,7 @@ void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
/* else: t->ref points to nothing, assume root/orphan commit */
}
- if (commit_tree(msg, tree_sha1, parents, result_sha1, NULL))
+ if (commit_tree(msg, tree_sha1, parents, result_sha1, NULL, NULL))
die("Failed to commit notes tree to database");
}
--
1.7.7.498.g3f2e50
^ permalink raw reply related
* [PATCH v4 3/5] log: --show-signature
From: Junio C Hamano @ 2011-10-20 0:37 UTC (permalink / raw)
To: git
In-Reply-To: <1319071023-31919-1-git-send-email-gitster@pobox.com>
This teaches the "log" family of commands to pass the GPG signature in the
commit objects to "gpg --verify" via the verify_signed_buffer() interface
used to verify signed tag objects. E.g.
$ git show --show-signature -s HEAD
shows GPG output in the header part of the output.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
commit.c | 34 ++++++++++++++++++++++++++++++++++
commit.h | 3 +++
log-tree.c | 39 +++++++++++++++++++++++++++++++++++++++
revision.c | 2 ++
revision.h | 1 +
5 files changed, 79 insertions(+), 0 deletions(-)
diff --git a/commit.c b/commit.c
index 4bff3cd..93045a2 100644
--- a/commit.c
+++ b/commit.c
@@ -848,6 +848,40 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid)
return 0;
}
+int parse_signed_commit(const unsigned char *sha1,
+ struct strbuf *payload, struct strbuf *signature)
+{
+ unsigned long size;
+ enum object_type type;
+ char *buffer = read_sha1_file(sha1, &type, &size);
+ int in_header, saw_signature = -1;
+ char *line;
+
+ if (!buffer || type != OBJ_COMMIT)
+ goto cleanup;
+
+ line = buffer;
+ in_header = 1;
+ saw_signature = 0;
+ while (*line) {
+ char *next = strchrnul(line, '\n');
+ if (*next)
+ next++;
+ if (in_header && !prefixcmp(line, gpg_sig_header)) {
+ const char *sig = line + gpg_sig_header_len;
+ strbuf_add(signature, sig, next - sig);
+ saw_signature = 1;
+ } else {
+ strbuf_add(payload, line, next - line);
+ }
+ if (*line == '\n')
+ in_header = 0;
+ line = next;
+ }
+ cleanup:
+ free(buffer);
+ return saw_signature;
+}
static const char commit_utf8_warn[] =
"Warning: commit message does not conform to UTF-8.\n"
diff --git a/commit.h b/commit.h
index 8c2419b..1885471 100644
--- a/commit.h
+++ b/commit.h
@@ -177,4 +177,7 @@ extern int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret,
const char *author, const char *sign_commit);
+extern int parse_signed_commit(const unsigned char *sha1,
+ struct strbuf *message, struct strbuf *signature);
+
#endif /* COMMIT_H */
diff --git a/log-tree.c b/log-tree.c
index 24c295e..f7b6976 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -8,6 +8,7 @@
#include "refs.h"
#include "string-list.h"
#include "color.h"
+#include "gpg-interface.h"
struct decoration name_decoration = { "object names" };
@@ -395,6 +396,41 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
*extra_headers_p = extra_headers;
}
+static void show_signature(struct rev_info *opt, struct commit *commit)
+{
+ struct strbuf payload = STRBUF_INIT;
+ struct strbuf signature = STRBUF_INIT;
+ struct strbuf gpg_output = STRBUF_INIT;
+ int status;
+ const char *color, *reset, *bol, *eol;
+
+ if (parse_signed_commit(commit->object.sha1, &payload, &signature) <= 0)
+ goto out;
+
+ status = verify_signed_buffer(payload.buf, payload.len,
+ signature.buf, signature.len,
+ &gpg_output);
+ if (status && !gpg_output.len)
+ strbuf_addstr(&gpg_output, "No signature\n");
+
+ color = diff_get_color_opt(&opt->diffopt,
+ status ? DIFF_WHITESPACE : DIFF_FRAGINFO);
+ reset = diff_get_color_opt(&opt->diffopt, DIFF_RESET);
+
+ bol = gpg_output.buf;
+ while (*bol) {
+ eol = strchrnul(bol, '\n');
+ printf("%s%.*s%s%s", color, (int)(eol - bol), bol, reset,
+ *eol ? "\n" : "");
+ bol = (*eol) ? (eol + 1) : eol;
+ }
+
+ out:
+ strbuf_release(&gpg_output);
+ strbuf_release(&payload);
+ strbuf_release(&signature);
+}
+
void show_log(struct rev_info *opt)
{
struct strbuf msgbuf = STRBUF_INIT;
@@ -502,6 +538,9 @@ void show_log(struct rev_info *opt)
}
}
+ if (opt->show_signature)
+ show_signature(opt, commit);
+
if (!commit->buffer)
return;
diff --git a/revision.c b/revision.c
index c46cfaa..860a312 100644
--- a/revision.c
+++ b/revision.c
@@ -1381,6 +1381,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->show_notes = 1;
revs->show_notes_given = 1;
revs->notes_opt.use_default_notes = 1;
+ } else if (!strcmp(arg, "--show-signature")) {
+ revs->show_signature = 1;
} else if (!prefixcmp(arg, "--show-notes=") ||
!prefixcmp(arg, "--notes=")) {
struct strbuf buf = STRBUF_INIT;
diff --git a/revision.h b/revision.h
index 3d64ada..198bb95 100644
--- a/revision.h
+++ b/revision.h
@@ -89,6 +89,7 @@ struct rev_info {
show_merge:1,
show_notes:1,
show_notes_given:1,
+ show_signature:1,
pretty_given:1,
abbrev_commit:1,
abbrev_commit_given:1,
--
1.7.7.498.g3f2e50
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox