diff options
author | Chris Marchesi <chrism@vancluevertech.com> | 2018-08-21 22:24:41 -0700 |
---|---|---|
committer | Chris Marchesi <chrism@vancluevertech.com> | 2018-08-21 22:24:41 -0700 |
commit | 2c2b532a525ab2c05f6e9675efd529a052121713 (patch) | |
tree | c77ddbd5dd328b89670c3ad695fce7bc491b4879 | |
parent | 8c3c8b30b3394677d8eb16b159bfe9b4f61726a8 (diff) | |
download | go-git-2c2b532a525ab2c05f6e9675efd529a052121713.tar.gz |
git: Canonicalize incoming annotated tag messages
Tag messages are highly sensitive to being in the expected format,
especially when encoding/decoding for PGP verification.
As such, we do a simple trimming of whitespace on the incoming message
and add a newline on the end, to ensure there are no surprises here.
Signed-off-by: Chris Marchesi <chrism@vancluevertech.com>
-rw-r--r-- | options.go | 8 | ||||
-rw-r--r-- | repository_test.go | 43 |
2 files changed, 50 insertions, 1 deletions
@@ -3,6 +3,7 @@ package git import ( "errors" "regexp" + "strings" "golang.org/x/crypto/openpgp" "gopkg.in/src-d/go-git.v4/config" @@ -389,7 +390,9 @@ var ( type TagObjectOptions struct { // Tagger defines the signature of the tag creator. Tagger *object.Signature - // Message defines the annotation of the tag. + // Message defines the annotation of the tag. It is canonicalized during + // validation into the format expected by git - no leading whitespace and + // ending in a newline. Message string // TargetType is the object type of the target. The object specified by // Target must be of this type. @@ -409,6 +412,9 @@ func (o *TagObjectOptions) Validate(r *Repository, hash plumbing.Hash) error { return ErrMissingMessage } + // Canonicalize the message into the expected message format. + o.Message = strings.TrimSpace(o.Message) + "\n" + if o.TargetType == plumbing.InvalidObject || o.TargetType == plumbing.AnyObject { return ErrBadObjectType } diff --git a/repository_test.go b/repository_test.go index 4fd26a1..fd80152 100644 --- a/repository_test.go +++ b/repository_test.go @@ -1455,6 +1455,49 @@ func (s *RepositorySuite) TestCreateTagSignedBadKey(c *C) { c.Assert(err, Equals, openpgperr.InvalidArgumentError("signing key is encrypted")) } +func (s *RepositorySuite) TestCreateTagCanonicalize(c *C) { + url := s.GetLocalRepositoryURL( + fixtures.ByURL("https://github.com/git-fixtures/tags.git").One(), + ) + + r, _ := Init(memory.NewStorage(), nil) + err := r.clone(context.Background(), &CloneOptions{URL: url}) + c.Assert(err, IsNil) + + h, err := r.Head() + c.Assert(err, IsNil) + + key := commitSignKey(c, true) + _, err = r.CreateTag("foobar", h.Hash(), &TagObjectOptions{ + Tagger: defaultSignature(), + Message: "\n\nfoo bar baz qux\n\nsome message here", + TargetType: plumbing.CommitObject, + SignKey: key, + }) + c.Assert(err, IsNil) + + _, obj, err := r.Tag("foobar") + c.Assert(err, IsNil) + c.Assert(obj, NotNil) + + // Assert the new canonicalized message. + c.Assert(obj.Message, Equals, "foo bar baz qux\n\nsome message here\n") + + // Verify the tag. + pks := new(bytes.Buffer) + pkw, err := armor.Encode(pks, openpgp.PublicKeyType, nil) + c.Assert(err, IsNil) + + err = key.Serialize(pkw) + c.Assert(err, IsNil) + err = pkw.Close() + c.Assert(err, IsNil) + + actual, err := obj.Verify(pks.String()) + c.Assert(err, IsNil) + c.Assert(actual.PrimaryKey, DeepEquals, key.PrimaryKey) +} + func (s *RepositorySuite) TestTagLightweight(c *C) { url := s.GetLocalRepositoryURL( fixtures.ByURL("https://github.com/git-fixtures/tags.git").One(), |