mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 06:27:05 +00:00
Reject custom marshalers from direct CBOR Marshal and Unmarshal.
Types that implement any of the stdlib text and JSON marshaler and unmarshaler interfaces without implementing the corresponding CBOR interfaces are currently rejected by the CBOR serializer. This is a temporary measure for the initial alpha; such types will ultimately be handled via automatic transcoding. The "cbor/direct" subpackage exports Marshal and Unmarshal functions to support the implementation of custom CBOR marshalling and unmarshalling behaviors, but did not include the safeguard against handling non-CBOR custom marshalers.
This commit is contained in:
parent
dc1d7f41ef
commit
0b7b42cc10
@ -23,14 +23,39 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes"
|
||||
)
|
||||
|
||||
// Marshal serializes a value to CBOR. If there is more than one way to encode the value, it will
|
||||
// make the same choice as the CBOR implementation of runtime.Serializer.
|
||||
//
|
||||
// Note: Support for CBOR is at an alpha stage. If the value (or, for composite types, any of its
|
||||
// nested values) implement any of the interfaces encoding.TextMarshaler, encoding.TextUnmarshaler,
|
||||
// encoding/json.Marshaler, or encoding/json.Unmarshaler, a non-nil error will be returned unless
|
||||
// the value also implements the corresponding CBOR interfaces. This limitation will ultimately be
|
||||
// removed in favor of automatic transcoding to CBOR.
|
||||
func Marshal(src interface{}) ([]byte, error) {
|
||||
if err := modes.RejectCustomMarshalers(src); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return modes.Encode.Marshal(src)
|
||||
}
|
||||
|
||||
// Unmarshal deserializes from CBOR into an addressable value. If there is more than one way to
|
||||
// unmarshal a value, it will make the same choice as the CBOR implementation of runtime.Serializer.
|
||||
//
|
||||
// Note: Support for CBOR is at an alpha stage. If the value (or, for composite types, any of its
|
||||
// nested values) implement any of the interfaces encoding.TextMarshaler, encoding.TextUnmarshaler,
|
||||
// encoding/json.Marshaler, or encoding/json.Unmarshaler, a non-nil error will be returned unless
|
||||
// the value also implements the corresponding CBOR interfaces. This limitation will ultimately be
|
||||
// removed in favor of automatic transcoding to CBOR.
|
||||
func Unmarshal(src []byte, dst interface{}) error {
|
||||
if err := modes.RejectCustomMarshalers(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
return modes.Decode.Unmarshal(src, dst)
|
||||
}
|
||||
|
||||
// Diagnose accepts well-formed CBOR bytes and returns a string representing the same data item in
|
||||
// human-readable diagnostic notation (RFC 8949 Section 8). The diagnostic notation is not meant to
|
||||
// be parsed.
|
||||
func Diagnose(src []byte) (string, error) {
|
||||
return modes.Diagnostic.Diagnose(src)
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package direct_test
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct"
|
||||
)
|
||||
|
||||
var _ json.Marshaler = CustomJSONMarshaler{}
|
||||
|
||||
type CustomJSONMarshaler struct{}
|
||||
|
||||
func (CustomJSONMarshaler) MarshalJSON() ([]byte, error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = CustomJSONUnmarshaler{}
|
||||
|
||||
type CustomJSONUnmarshaler struct{}
|
||||
|
||||
func (CustomJSONUnmarshaler) UnmarshalJSON([]byte) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
var _ encoding.TextMarshaler = CustomTextMarshaler{}
|
||||
|
||||
type CustomTextMarshaler struct{}
|
||||
|
||||
func (CustomTextMarshaler) MarshalText() ([]byte, error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
var _ encoding.TextUnmarshaler = CustomTextUnmarshaler{}
|
||||
|
||||
type CustomTextUnmarshaler struct{}
|
||||
|
||||
func (CustomTextUnmarshaler) UnmarshalText([]byte) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
func TestRejectsCustom(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
value interface{}
|
||||
iface reflect.Type
|
||||
}{
|
||||
{value: CustomJSONMarshaler{}, iface: reflect.TypeFor[json.Marshaler]()},
|
||||
{value: CustomJSONUnmarshaler{}, iface: reflect.TypeFor[json.Unmarshaler]()},
|
||||
{value: CustomTextMarshaler{}, iface: reflect.TypeFor[encoding.TextMarshaler]()},
|
||||
{value: CustomTextUnmarshaler{}, iface: reflect.TypeFor[encoding.TextUnmarshaler]()},
|
||||
} {
|
||||
t.Run(fmt.Sprintf("%T", tc.value), func(t *testing.T) {
|
||||
want := fmt.Sprintf("unable to serialize %T: %T implements %s without corresponding cbor interface", tc.value, tc.value, tc.iface.String())
|
||||
if _, err := direct.Marshal(tc.value); err == nil || err.Error() != want {
|
||||
t.Errorf("want error: %q, got: %v", want, err)
|
||||
}
|
||||
if err := direct.Unmarshal(nil, tc.value); err == nil || err.Error() != want {
|
||||
t.Errorf("want error: %q, got: %v", want, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user