From 4a5b3ef9b90b2a724fbe9557b4cb15a65d2be87b Mon Sep 17 00:00:00 2001 From: Hiroshi Ioka Date: Sun, 16 Oct 2016 14:31:18 +0900 Subject: [PATCH] encoding/asn1: return error instead of dereferencing nil *big.Int in marshaling Fixes #17461 Change-Id: I9954f6ae46c7e15560d7460841be8f2bc37233a9 Reviewed-on: https://go-review.googlesource.com/31121 Reviewed-by: Adam Langley Run-TryBot: Adam Langley TryBot-Result: Gobot Gobot --- src/encoding/asn1/asn1_test.go | 6 +++++- src/encoding/asn1/marshal.go | 18 +++++++++++------- src/encoding/asn1/marshal_test.go | 24 ++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/encoding/asn1/asn1_test.go b/src/encoding/asn1/asn1_test.go index 81f4dba8c2..8ee46d4565 100644 --- a/src/encoding/asn1/asn1_test.go +++ b/src/encoding/asn1/asn1_test.go @@ -132,7 +132,11 @@ func TestParseBigInt(t *testing.T) { if ret.String() != test.base10 { t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10) } - e := makeBigInt(ret) + e, err := makeBigInt(ret) + if err != nil { + t.Errorf("%d: err=%q", i, err) + continue + } result := make([]byte, e.Len()) e.Encode(result) if !bytes.Equal(result, test.in) { diff --git a/src/encoding/asn1/marshal.go b/src/encoding/asn1/marshal.go index f0664d3d46..444c7f3642 100644 --- a/src/encoding/asn1/marshal.go +++ b/src/encoding/asn1/marshal.go @@ -150,7 +150,11 @@ func appendBase128Int(dst []byte, n int64) []byte { return dst } -func makeBigInt(n *big.Int) encoder { +func makeBigInt(n *big.Int) (encoder, error) { + if n == nil { + return nil, StructuralError{"empty integer"} + } + if n.Sign() < 0 { // A negative number has to be converted to two's-complement // form. So we'll invert and subtract 1. If the @@ -163,20 +167,20 @@ func makeBigInt(n *big.Int) encoder { bytes[i] ^= 0xff } if len(bytes) == 0 || bytes[0]&0x80 == 0 { - return multiEncoder([]encoder{byteFFEncoder, bytesEncoder(bytes)}) + return multiEncoder([]encoder{byteFFEncoder, bytesEncoder(bytes)}), nil } - return bytesEncoder(bytes) + return bytesEncoder(bytes), nil } else if n.Sign() == 0 { // Zero is written as a single 0 zero rather than no bytes. - return byte00Encoder + return byte00Encoder, nil } else { bytes := n.Bytes() if len(bytes) > 0 && bytes[0]&0x80 != 0 { // We'll have to pad this with 0x00 in order to stop it // looking like a negative number. - return multiEncoder([]encoder{byte00Encoder, bytesEncoder(bytes)}) + return multiEncoder([]encoder{byte00Encoder, bytesEncoder(bytes)}), nil } - return bytesEncoder(bytes) + return bytesEncoder(bytes), nil } } @@ -409,7 +413,7 @@ func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error case objectIdentifierType: return makeObjectIdentifier(value.Interface().(ObjectIdentifier)) case bigIntType: - return makeBigInt(value.Interface().(*big.Int)), nil + return makeBigInt(value.Interface().(*big.Int)) } switch v := value; v.Kind() { diff --git a/src/encoding/asn1/marshal_test.go b/src/encoding/asn1/marshal_test.go index 6af770fcc3..10db1aa575 100644 --- a/src/encoding/asn1/marshal_test.go +++ b/src/encoding/asn1/marshal_test.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/hex" "math/big" + "strings" "testing" "time" ) @@ -167,6 +168,29 @@ func TestMarshal(t *testing.T) { } } +type marshalErrTest struct { + in interface{} + err string +} + +var marshalErrTests = []marshalErrTest{ + {bigIntStruct{nil}, "empty integer"}, +} + +func TestMarshalError(t *testing.T) { + for i, test := range marshalErrTests { + _, err := Marshal(test.in) + if err == nil { + t.Errorf("#%d should fail, but success", i) + continue + } + + if !strings.Contains(err.Error(), test.err) { + t.Errorf("#%d got: %v want %v", i, err, test.err) + } + } +} + func TestInvalidUTF8(t *testing.T) { _, err := Marshal(string([]byte{0xff, 0xff})) if err == nil { -- 2.48.1