diff options
author | Kyle Isom <kyle@gokyle.net> | 2015-06-04 13:23:25 -0700 |
---|---|---|
committer | Adam Langley <agl@golang.org> | 2015-06-13 19:59:16 +0000 |
commit | 38e3427b2ffd90c4eca3643069a21c6e936566de (patch) | |
tree | 38fc475399f76b73ae4a48e505f5727d59bb42bc /src/encoding/asn1 | |
parent | a1fe3b5046d9f7249c04ce942f4d2d1d771bff40 (diff) | |
download | go-38e3427b2ffd90c4eca3643069a21c6e936566de.tar.gz go-38e3427b2ffd90c4eca3643069a21c6e936566de.zip |
encoding/asn1: check bounds when parsing tag and length
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>
Diffstat (limited to 'src/encoding/asn1')
-rw-r--r-- | src/encoding/asn1/asn1.go | 11 | ||||
-rw-r--r-- | src/encoding/asn1/asn1_test.go | 19 |
2 files changed, 30 insertions, 0 deletions
diff --git a/src/encoding/asn1/asn1.go b/src/encoding/asn1/asn1.go index 7172c1c786..b4457e02dc 100644 --- a/src/encoding/asn1/asn1.go +++ b/src/encoding/asn1/asn1.go @@ -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) diff --git a/src/encoding/asn1/asn1_test.go b/src/encoding/asn1/asn1_test.go index 1a2ae2569f..32e9ff2b0c 100644 --- a/src/encoding/asn1/asn1_test.go +++ b/src/encoding/asn1/asn1_test.go @@ -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") + } +} |