Commit 38e3427b authored by Kyle Isom's avatar Kyle Isom Committed by Adam Langley

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/10712Reviewed-by: 's avatarAdam Langley <agl@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
parent a1fe3b50
...@@ -20,6 +20,7 @@ package asn1 ...@@ -20,6 +20,7 @@ package asn1
// everything by any means. // everything by any means.
import ( import (
"errors"
"fmt" "fmt"
"math/big" "math/big"
"reflect" "reflect"
...@@ -389,6 +390,12 @@ type RawContent []byte ...@@ -389,6 +390,12 @@ type RawContent []byte
// don't distinguish between ordered and unordered objects in this code. // don't distinguish between ordered and unordered objects in this code.
func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) { func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) {
offset = initOffset 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] b := bytes[offset]
offset++ offset++
ret.class = int(b >> 6) ret.class = int(b >> 6)
...@@ -611,6 +618,10 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam ...@@ -611,6 +618,10 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
if params.application { if params.application {
expectedClass = classApplication 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.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) {
if t.length > 0 { if t.length > 0 {
t, offset, err = parseTagAndLength(bytes, offset) t, offset, err = parseTagAndLength(bytes, offset)
......
...@@ -867,3 +867,22 @@ func TestImplicitTaggedTime(t *testing.T) { ...@@ -867,3 +867,22 @@ func TestImplicitTaggedTime(t *testing.T) {
t.Errorf("Wrong result. Got %v, want %v", result.Time, expected) 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")
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment