]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/asn1: fix explicitly tagged Times.
authorAdam Langley <agl@golang.org>
Fri, 10 Oct 2014 00:37:40 +0000 (17:37 -0700)
committerAdam Langley <agl@golang.org>
Fri, 10 Oct 2014 00:37:40 +0000 (17:37 -0700)
https://golang.org/cl/153770043/ tried to fix the case where a
implicitly tagged Time, that happened to have the same tag as
GENERALIZEDTIME, shouldn't be parsed as a GENERALIZEDTIME.

It did so, mistakenly, by testing whether params.tag != nil. But
explicitly tagged values also have a non-nil tag and there the inner
tag actually does encode the type of the value.

This change instead tests whether the tag class is UNIVERSAL before
assuming that the tag contains type information.

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/152380044

src/encoding/asn1/asn1.go
src/encoding/asn1/asn1_test.go

index 3aeb3dcc4bcde4255088a8e6b484ec019bb68fcb..8b3d1b34121c6cc78019806b2bbb76999a6912f5 100644 (file)
@@ -640,7 +640,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
        // when it sees a string, so if we see a different string type on the
        // wire, we change the universal type to match.
        if universalTag == tagPrintableString {
-               if params.tag == nil {
+               if t.class == classUniversal {
                        switch t.tag {
                        case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
                                universalTag = t.tag
@@ -652,7 +652,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 
        // Special case for time: UTCTime and GeneralizedTime both map to the
        // Go type time.Time.
-       if universalTag == tagUTCTime && params.tag == nil && t.tag == tagGeneralizedTime {
+       if universalTag == tagUTCTime && t.tag == tagGeneralizedTime && t.class == classUniversal {
                universalTag = tagGeneralizedTime
        }
 
index b94d59d36939d02fc8ceb9403630d765800c8e1f..4e864d08ac0a96ba42dd45ce5c94efb4f48d1914 100644 (file)
@@ -817,3 +817,51 @@ func TestStringSlice(t *testing.T) {
                }
        }
 }
+
+type explicitTaggedTimeTest struct {
+       Time time.Time `asn1:"explicit,tag:0"`
+}
+
+var explicitTaggedTimeTestData = []struct {
+       in  []byte
+       out explicitTaggedTimeTest
+}{
+       {[]byte{0x30, 0x11, 0xa0, 0xf, 0x17, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'},
+               explicitTaggedTimeTest{time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC)}},
+       {[]byte{0x30, 0x17, 0xa0, 0xf, 0x18, 0x13, '2', '0', '1', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '+', '0', '6', '0', '7'},
+               explicitTaggedTimeTest{time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}},
+}
+
+func TestExplicitTaggedTime(t *testing.T) {
+       // Test that a time.Time will match either tagUTCTime or
+       // tagGeneralizedTime.
+       for i, test := range explicitTaggedTimeTestData {
+               var got explicitTaggedTimeTest
+               _, err := Unmarshal(test.in, &got)
+               if err != nil {
+                       t.Errorf("Unmarshal failed at index %d %v", i, err)
+               }
+               if !got.Time.Equal(test.out.Time) {
+                       t.Errorf("#%d: got %v, want %v", i, got.Time, test.out.Time)
+               }
+       }
+}
+
+type implicitTaggedTimeTest struct {
+       Time time.Time `asn1:"tag:24"`
+}
+
+func TestImplicitTaggedTime(t *testing.T) {
+       // An implicitly tagged time value, that happens to have an implicit
+       // tag equal to a GENERALIZEDTIME, should still be parsed as a UTCTime.
+       // (There's no "timeType" in fieldParameters to determine what type of
+       // time should be expected when implicitly tagged.)
+       der := []byte{0x30, 0x0f, 0x80 | 24, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'}
+       var result implicitTaggedTimeTest
+       if _, err := Unmarshal(der, &result); err != nil {
+               t.Fatalf("Error while parsing: %s", err)
+       }
+       if expected := time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC); !result.Time.Equal(expected) {
+               t.Errorf("Wrong result. Got %v, want %v", result.Time, expected)
+       }
+}