]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/asn1: check bounds when parsing tag and length
authorKyle Isom <kyle@gokyle.net>
Thu, 4 Jun 2015 20:23:25 +0000 (13:23 -0700)
committerAdam Langley <agl@golang.org>
Sat, 13 Jun 2015 19:59:16 +0000 (19:59 +0000)
This was found while fuzzing another program, triggering a panic in
x509.ParseECPrivateKey.

Fixes #11154

Change-Id: Ief35ead38adf14caec4d37b9eacf8a92e67cd1e6
Reviewed-on: https://go-review.googlesource.com/10712
Reviewed-by: Adam Langley <agl@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>

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

index 7172c1c78601783bddee303d43ab43d71b520113..b4457e02dc05ce43e72f184b1fb6f43a68c13a56 100644 (file)
@@ -20,6 +20,7 @@ package asn1
 // everything by any means.
 
 import (
+       "errors"
        "fmt"
        "math/big"
        "reflect"
@@ -389,6 +390,12 @@ type RawContent []byte
 // don't distinguish between ordered and unordered objects in this code.
 func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) {
        offset = initOffset
+       // parseTagAndLength should not be called without at least a single
+       // byte to read. Thus this check is for robustness:
+       if offset >= len(bytes) {
+               err = errors.New("asn1: internal error in parseTagAndLength")
+               return
+       }
        b := bytes[offset]
        offset++
        ret.class = int(b >> 6)
@@ -611,6 +618,10 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                if params.application {
                        expectedClass = classApplication
                }
+               if offset == len(bytes) {
+                       err = StructuralError{"explicit tag has no child"}
+                       return
+               }
                if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) {
                        if t.length > 0 {
                                t, offset, err = parseTagAndLength(bytes, offset)
index 1a2ae2569f8fb6def8f8b7a17889cb96cd055cad..32e9ff2b0c09c69a856323e3ab451f89e1a9d5b6 100644 (file)
@@ -867,3 +867,22 @@ func TestImplicitTaggedTime(t *testing.T) {
                t.Errorf("Wrong result. Got %v, want %v", result.Time, expected)
        }
 }
+
+type truncatedExplicitTagTest struct {
+       Test int `asn1:"explicit,tag:0"`
+}
+
+func TestTruncatedExplicitTag(t *testing.T) {
+       // This crashed Unmarshal in the past. See #11154.
+       der := []byte{
+               0x30, // SEQUENCE
+               0x02, // two bytes long
+               0xa0, // context-specific, tag 0
+               0x30, // 48 bytes long
+       }
+
+       var result truncatedExplicitTagTest
+       if _, err := Unmarshal(der, &result); err == nil {
+               t.Error("Unmarshal returned without error")
+       }
+}