mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-14 21:53:52 +00:00
Merge pull request #125420 from benluddy/cbor-bignum-bigint
KEP-4222: Reject math/big.Int on encode and bignum tags on decode for CBOR.
This commit is contained in:
@@ -121,7 +121,6 @@ func TestAppendixA(t *testing.T) {
|
|||||||
{
|
{
|
||||||
example: hex("c249010000000000000000"),
|
example: hex("c249010000000000000000"),
|
||||||
reject: "decoding tagged positive bigint value to interface{} can't reproduce this value without losing distinction between float and integer",
|
reject: "decoding tagged positive bigint value to interface{} can't reproduce this value without losing distinction between float and integer",
|
||||||
fixme: "decoding bigint to interface{} must not produce math/big.Int",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
example: hex("3bffffffffffffffff"),
|
example: hex("3bffffffffffffffff"),
|
||||||
@@ -130,7 +129,6 @@ func TestAppendixA(t *testing.T) {
|
|||||||
{
|
{
|
||||||
example: hex("c349010000000000000000"),
|
example: hex("c349010000000000000000"),
|
||||||
reject: "-18446744073709551617 overflows int64 and falling back to float64 (as with JSON) loses distinction between float and integer",
|
reject: "-18446744073709551617 overflows int64 and falling back to float64 (as with JSON) loses distinction between float and integer",
|
||||||
fixme: "decoding negative bigint to interface{} must not produce math/big.Int",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
example: hex("20"),
|
example: hex("20"),
|
||||||
|
@@ -96,6 +96,10 @@ var Decode cbor.DecMode = func() cbor.DecMode {
|
|||||||
// representation (RFC 8259 Section 6).
|
// representation (RFC 8259 Section 6).
|
||||||
NaN: cbor.NaNDecodeForbidden,
|
NaN: cbor.NaNDecodeForbidden,
|
||||||
Inf: cbor.InfDecodeForbidden,
|
Inf: cbor.InfDecodeForbidden,
|
||||||
|
|
||||||
|
// Reject the arbitrary-precision integer tags because they can't be faithfully
|
||||||
|
// roundtripped through the allowable Unstructured types.
|
||||||
|
BignumTag: cbor.BignumTagForbidden,
|
||||||
}.DecMode()
|
}.DecMode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@@ -739,29 +739,25 @@ func TestDecode(t *testing.T) {
|
|||||||
|
|
||||||
group(t, "unsigned bignum", []test{
|
group(t, "unsigned bignum", []test{
|
||||||
{
|
{
|
||||||
name: "rejected",
|
name: "rejected",
|
||||||
in: hex("c249010000000000000000"), // 2(18446744073709551616)
|
in: hex("c249010000000000000000"), // 2(18446744073709551616)
|
||||||
fixme: "decoding cbor data tagged with 2 produces big.Int instead of rejecting",
|
assertOnError: assertOnConcreteError(func(t *testing.T, e *cbor.UnacceptableDataItemError) {
|
||||||
assertOnError: func(t *testing.T, e error) {
|
if diff := cmp.Diff(&cbor.UnacceptableDataItemError{CBORType: "tag", Message: "bignum"}, e); diff != "" {
|
||||||
// TODO: Once this can pass, make the assertion stronger.
|
t.Errorf("unexpected error diff:\n%s", diff)
|
||||||
if e == nil {
|
|
||||||
t.Error("expected non-nil error")
|
|
||||||
}
|
}
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
group(t, "negative bignum", []test{
|
group(t, "negative bignum", []test{
|
||||||
{
|
{
|
||||||
name: "rejected",
|
name: "rejected",
|
||||||
in: hex("c349010000000000000000"), // 3(-18446744073709551617)
|
in: hex("c349010000000000000000"), // 3(-18446744073709551617)
|
||||||
fixme: "decoding cbor data tagged with 3 produces big.Int instead of rejecting",
|
assertOnError: assertOnConcreteError(func(t *testing.T, e *cbor.UnacceptableDataItemError) {
|
||||||
assertOnError: func(t *testing.T, e error) {
|
if diff := cmp.Diff(&cbor.UnacceptableDataItemError{CBORType: "tag", Message: "bignum"}, e); diff != "" {
|
||||||
// TODO: Once this can pass, make the assertion stronger.
|
t.Errorf("unexpected error diff:\n%s", diff)
|
||||||
if e == nil {
|
|
||||||
t.Error("expected non-nil error")
|
|
||||||
}
|
}
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -37,11 +37,10 @@ var Encode cbor.EncMode = func() cbor.EncMode {
|
|||||||
NaNConvert: cbor.NaNConvertReject,
|
NaNConvert: cbor.NaNConvertReject,
|
||||||
InfConvert: cbor.InfConvertReject,
|
InfConvert: cbor.InfConvertReject,
|
||||||
|
|
||||||
// Prefer encoding math/big.Int to one of the 64-bit integer types if it fits. When
|
// Error on attempt to encode math/big.Int values, which can't be faithfully
|
||||||
// later decoded into Unstructured, the set of allowable concrete numeric types is
|
// roundtripped through Unstructured in general (the dynamic numeric types allowed
|
||||||
// limited to int64 and float64, so the distinction between big integer and integer
|
// in Unstructured are limited to float64 and int64).
|
||||||
// can't be preserved.
|
BigIntConvert: cbor.BigIntConvertReject,
|
||||||
BigIntConvert: cbor.BigIntConvertShortest,
|
|
||||||
|
|
||||||
// MarshalJSON for time.Time writes RFC3339 with nanos.
|
// MarshalJSON for time.Time writes RFC3339 with nanos.
|
||||||
Time: cbor.TimeRFC3339Nano,
|
Time: cbor.TimeRFC3339Nano,
|
||||||
|
@@ -18,6 +18,8 @@ package modes_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/fxamacker/cbor/v2"
|
"github.com/fxamacker/cbor/v2"
|
||||||
@@ -53,6 +55,15 @@ func TestEncode(t *testing.T) {
|
|||||||
want: []byte{0xa1, 0x41, 0x41, 0x02}, // {"A": 2}
|
want: []byte{0xa1, 0x41, 0x41, 0x02}, // {"A": 2}
|
||||||
assertOnError: assertNilError,
|
assertOnError: assertNilError,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "math/big.Int values are rejected",
|
||||||
|
in: big.NewInt(1),
|
||||||
|
assertOnError: assertOnConcreteError(func(t *testing.T, got *cbor.UnsupportedTypeError) {
|
||||||
|
if want := (&cbor.UnsupportedTypeError{Type: reflect.TypeFor[big.Int]()}); *want != *got {
|
||||||
|
t.Errorf("unexpected error, got %#v (%q), want %#v (%q)", got, got.Error(), want, want.Error())
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
encModes := tc.modes
|
encModes := tc.modes
|
||||||
if len(encModes) == 0 {
|
if len(encModes) == 0 {
|
||||||
@@ -68,7 +79,7 @@ func TestEncode(t *testing.T) {
|
|||||||
t.Run(fmt.Sprintf("mode=%s/%s", modeName, tc.name), func(t *testing.T) {
|
t.Run(fmt.Sprintf("mode=%s/%s", modeName, tc.name), func(t *testing.T) {
|
||||||
out, err := encMode.Marshal(tc.in)
|
out, err := encMode.Marshal(tc.in)
|
||||||
tc.assertOnError(t, err)
|
tc.assertOnError(t, err)
|
||||||
if diff := cmp.Diff(tc.want, out); diff != "" {
|
if diff := cmp.Diff(tc.want, out, cmp.Comparer(func(a, b reflect.Type) bool { return a == b })); diff != "" {
|
||||||
t.Errorf("unexpected output:\n%s", diff)
|
t.Errorf("unexpected output:\n%s", diff)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user