aboutsummaryrefslogtreecommitdiff
path: root/src/encoding
diff options
context:
space:
mode:
authorKimMachineGun <geon0250@gmail.com>2020-09-29 10:03:38 +0000
committerFilippo Valsorda <filippo@golang.org>2020-09-29 10:31:59 +0000
commita28edbfca276307b228eb4b154bc2d137a3cba4a (patch)
tree7a364b1e10eef488549543a4c7bee6771b4351f3 /src/encoding
parent79e681d2a291142aa0ac8297229e182b2d1a78ac (diff)
downloadgo-a28edbfca276307b228eb4b154bc2d137a3cba4a.tar.gz
go-a28edbfca276307b228eb4b154bc2d137a3cba4a.zip
encoding/asn1: error instead of panic on invalid value to Unmarshal
Changes Unmarshal to return an error, instead of panicking when its value is nil or not a pointer. This change matches the behavior of other encoding packages like json. Fixes #41509. Change-Id: I92c3af3a960144566e4c2b55d00c3a6fe477c8d5 GitHub-Last-Rev: c668b6e4ad826f84542c2675eb31ccfb010c45bb GitHub-Pull-Request: golang/go#41485 Reviewed-on: https://go-review.googlesource.com/c/go/+/255881 Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com> Reviewed-by: Filippo Valsorda <filippo@golang.org> Trust: Emmanuel Odeke <emm.odeke@gmail.com>
Diffstat (limited to 'src/encoding')
-rw-r--r--src/encoding/asn1/asn1.go27
-rw-r--r--src/encoding/asn1/asn1_test.go23
2 files changed, 47 insertions, 3 deletions
diff --git a/src/encoding/asn1/asn1.go b/src/encoding/asn1/asn1.go
index d809dde278..fa3d4e327b 100644
--- a/src/encoding/asn1/asn1.go
+++ b/src/encoding/asn1/asn1.go
@@ -1035,7 +1035,8 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
// Unmarshal parses the DER-encoded ASN.1 data structure b
// and uses the reflect package to fill in an arbitrary value pointed at by val.
// Because Unmarshal uses the reflect package, the structs
-// being written to must use upper case field names.
+// being written to must use upper case field names. If val
+// is nil or not a pointer, Unmarshal returns an error.
//
// After parsing b, any bytes that were leftover and not used to fill
// val will be returned in rest. When parsing a SEQUENCE into a struct,
@@ -1095,11 +1096,31 @@ func Unmarshal(b []byte, val interface{}) (rest []byte, err error) {
return UnmarshalWithParams(b, val, "")
}
+// An invalidUnmarshalError describes an invalid argument passed to Unmarshal.
+// (The argument to Unmarshal must be a non-nil pointer.)
+type invalidUnmarshalError struct {
+ Type reflect.Type
+}
+
+func (e *invalidUnmarshalError) Error() string {
+ if e.Type == nil {
+ return "asn1: Unmarshal recipient value is nil"
+ }
+
+ if e.Type.Kind() != reflect.Ptr {
+ return "asn1: Unmarshal recipient value is non-pointer " + e.Type.String()
+ }
+ return "asn1: Unmarshal recipient value is nil " + e.Type.String()
+}
+
// UnmarshalWithParams allows field parameters to be specified for the
// top-level element. The form of the params is the same as the field tags.
func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err error) {
- v := reflect.ValueOf(val).Elem()
- offset, err := parseField(v, b, 0, parseFieldParameters(params))
+ v := reflect.ValueOf(val)
+ if v.Kind() != reflect.Ptr || v.IsNil() {
+ return nil, &invalidUnmarshalError{reflect.TypeOf(val)}
+ }
+ offset, err := parseField(v.Elem(), b, 0, parseFieldParameters(params))
if err != nil {
return nil, err
}
diff --git a/src/encoding/asn1/asn1_test.go b/src/encoding/asn1/asn1_test.go
index 8daae97faa..8985538468 100644
--- a/src/encoding/asn1/asn1_test.go
+++ b/src/encoding/asn1/asn1_test.go
@@ -518,6 +518,29 @@ func TestUnmarshal(t *testing.T) {
}
}
+func TestUnmarshalWithNilOrNonPointer(t *testing.T) {
+ tests := []struct {
+ b []byte
+ v interface{}
+ want string
+ }{
+ {b: []byte{0x05, 0x00}, v: nil, want: "asn1: Unmarshal recipient value is nil"},
+ {b: []byte{0x05, 0x00}, v: RawValue{}, want: "asn1: Unmarshal recipient value is non-pointer asn1.RawValue"},
+ {b: []byte{0x05, 0x00}, v: (*RawValue)(nil), want: "asn1: Unmarshal recipient value is nil *asn1.RawValue"},
+ }
+
+ for _, test := range tests {
+ _, err := Unmarshal(test.b, test.v)
+ if err == nil {
+ t.Errorf("Unmarshal expecting error, got nil")
+ continue
+ }
+ if g, w := err.Error(), test.want; g != w {
+ t.Errorf("InvalidUnmarshalError mismatch\nGot: %q\nWant: %q", g, w)
+ }
+ }
+}
+
type Certificate struct {
TBSCertificate TBSCertificate
SignatureAlgorithm AlgorithmIdentifier