Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 2c2b532

Browse files
committed
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>
1 parent 8c3c8b3 commit 2c2b532

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

options.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package git
33
import (
44
"errors"
55
"regexp"
6+
"strings"
67

78
"golang.org/x/crypto/openpgp"
89
"gopkg.in/src-d/go-git.v4/config"
@@ -389,7 +390,9 @@ var (
389390
type TagObjectOptions struct {
390391
// Tagger defines the signature of the tag creator.
391392
Tagger *object.Signature
392-
// Message defines the annotation of the tag.
393+
// Message defines the annotation of the tag. It is canonicalized during
394+
// validation into the format expected by git - no leading whitespace and
395+
// ending in a newline.
393396
Message string
394397
// TargetType is the object type of the target. The object specified by
395398
// Target must be of this type.
@@ -409,6 +412,9 @@ func (o *TagObjectOptions) Validate(r *Repository, hash plumbing.Hash) error {
409412
return ErrMissingMessage
410413
}
411414

415+
// Canonicalize the message into the expected message format.
416+
o.Message = strings.TrimSpace(o.Message) + "\n"
417+
412418
if o.TargetType == plumbing.InvalidObject || o.TargetType == plumbing.AnyObject {
413419
return ErrBadObjectType
414420
}

repository_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,49 @@ func (s *RepositorySuite) TestCreateTagSignedBadKey(c *C) {
14551455
c.Assert(err, Equals, openpgperr.InvalidArgumentError("signing key is encrypted"))
14561456
}
14571457

1458+
func (s *RepositorySuite) TestCreateTagCanonicalize(c *C) {
1459+
url := s.GetLocalRepositoryURL(
1460+
fixtures.ByURL("https://github.com/git-fixtures/tags.git").One(),
1461+
)
1462+
1463+
r, _ := Init(memory.NewStorage(), nil)
1464+
err := r.clone(context.Background(), &CloneOptions{URL: url})
1465+
c.Assert(err, IsNil)
1466+
1467+
h, err := r.Head()
1468+
c.Assert(err, IsNil)
1469+
1470+
key := commitSignKey(c, true)
1471+
_, err = r.CreateTag("foobar", h.Hash(), &TagObjectOptions{
1472+
Tagger: defaultSignature(),
1473+
Message: "\n\nfoo bar baz qux\n\nsome message here",
1474+
TargetType: plumbing.CommitObject,
1475+
SignKey: key,
1476+
})
1477+
c.Assert(err, IsNil)
1478+
1479+
_, obj, err := r.Tag("foobar")
1480+
c.Assert(err, IsNil)
1481+
c.Assert(obj, NotNil)
1482+
1483+
// Assert the new canonicalized message.
1484+
c.Assert(obj.Message, Equals, "foo bar baz qux\n\nsome message here\n")
1485+
1486+
// Verify the tag.
1487+
pks := new(bytes.Buffer)
1488+
pkw, err := armor.Encode(pks, openpgp.PublicKeyType, nil)
1489+
c.Assert(err, IsNil)
1490+
1491+
err = key.Serialize(pkw)
1492+
c.Assert(err, IsNil)
1493+
err = pkw.Close()
1494+
c.Assert(err, IsNil)
1495+
1496+
actual, err := obj.Verify(pks.String())
1497+
c.Assert(err, IsNil)
1498+
c.Assert(actual.PrimaryKey, DeepEquals, key.PrimaryKey)
1499+
}
1500+
14581501
func (s *RepositorySuite) TestTagLightweight(c *C) {
14591502
url := s.GetLocalRepositoryURL(
14601503
fixtures.ByURL("https://github.com/git-fixtures/tags.git").One(),

0 commit comments

Comments
 (0)