aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/encoding/asn1/asn1.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/encoding/asn1/asn1.go')
-rw-r--r--libgo/go/encoding/asn1/asn1.go84
1 files changed, 45 insertions, 39 deletions
diff --git a/libgo/go/encoding/asn1/asn1.go b/libgo/go/encoding/asn1/asn1.go
index d809dde..7c260b4 100644
--- a/libgo/go/encoding/asn1/asn1.go
+++ b/libgo/go/encoding/asn1/asn1.go
@@ -851,53 +851,37 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
offset += t.length
// We deal with the structures defined in this package first.
- switch fieldType {
- case rawValueType:
- result := RawValue{t.class, t.tag, t.isCompound, innerBytes, bytes[initOffset:offset]}
- v.Set(reflect.ValueOf(result))
+ switch v := v.Addr().Interface().(type) {
+ case *RawValue:
+ *v = RawValue{t.class, t.tag, t.isCompound, innerBytes, bytes[initOffset:offset]}
return
- case objectIdentifierType:
- newSlice, err1 := parseObjectIdentifier(innerBytes)
- v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice)))
- if err1 == nil {
- reflect.Copy(v, reflect.ValueOf(newSlice))
- }
- err = err1
+ case *ObjectIdentifier:
+ *v, err = parseObjectIdentifier(innerBytes)
return
- case bitStringType:
- bs, err1 := parseBitString(innerBytes)
- if err1 == nil {
- v.Set(reflect.ValueOf(bs))
- }
- err = err1
+ case *BitString:
+ *v, err = parseBitString(innerBytes)
return
- case timeType:
- var time time.Time
- var err1 error
+ case *time.Time:
if universalTag == TagUTCTime {
- time, err1 = parseUTCTime(innerBytes)
- } else {
- time, err1 = parseGeneralizedTime(innerBytes)
- }
- if err1 == nil {
- v.Set(reflect.ValueOf(time))
+ *v, err = parseUTCTime(innerBytes)
+ return
}
- err = err1
+ *v, err = parseGeneralizedTime(innerBytes)
return
- case enumeratedType:
+ case *Enumerated:
parsedInt, err1 := parseInt32(innerBytes)
if err1 == nil {
- v.SetInt(int64(parsedInt))
+ *v = Enumerated(parsedInt)
}
err = err1
return
- case flagType:
- v.SetBool(true)
+ case *Flag:
+ *v = true
return
- case bigIntType:
+ case **big.Int:
parsedInt, err1 := parseBigInt(innerBytes)
if err1 == nil {
- v.Set(reflect.ValueOf(parsedInt))
+ *v = parsedInt
}
err = err1
return
@@ -1035,7 +1019,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,
@@ -1085,9 +1070,10 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
// If the type of the first field of a structure is RawContent then the raw
// ASN1 contents of the struct will be stored in it.
//
-// If the type name of a slice element ends with "SET" then it's treated as if
-// the "set" tag was set on it. This can be used with nested slices where a
-// struct tag cannot be given.
+// If the name of a slice type ends with "SET" then it's treated as if
+// the "set" tag was set on it. This results in interpreting the type as a
+// SET OF x rather than a SEQUENCE OF x. This can be used with nested slices
+// where a struct tag cannot be given.
//
// Other ASN.1 types are not supported; if it encounters them,
// Unmarshal returns a parse error.
@@ -1095,11 +1081,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
}