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:
Kubernetes Prow Robot
2024-06-24 15:46:38 -07:00
committed by GitHub
5 changed files with 32 additions and 24 deletions

View File

@@ -121,7 +121,6 @@ func TestAppendixA(t *testing.T) {
{
example: hex("c249010000000000000000"),
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"),
@@ -130,7 +129,6 @@ func TestAppendixA(t *testing.T) {
{
example: hex("c349010000000000000000"),
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"),

View File

@@ -96,6 +96,10 @@ var Decode cbor.DecMode = func() cbor.DecMode {
// representation (RFC 8259 Section 6).
NaN: cbor.NaNDecodeForbidden,
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()
if err != nil {
panic(err)

View File

@@ -741,13 +741,11 @@ func TestDecode(t *testing.T) {
{
name: "rejected",
in: hex("c249010000000000000000"), // 2(18446744073709551616)
fixme: "decoding cbor data tagged with 2 produces big.Int instead of rejecting",
assertOnError: func(t *testing.T, e error) {
// TODO: Once this can pass, make the assertion stronger.
if e == nil {
t.Error("expected non-nil error")
assertOnError: assertOnConcreteError(func(t *testing.T, e *cbor.UnacceptableDataItemError) {
if diff := cmp.Diff(&cbor.UnacceptableDataItemError{CBORType: "tag", Message: "bignum"}, e); diff != "" {
t.Errorf("unexpected error diff:\n%s", diff)
}
},
}),
},
})
@@ -755,13 +753,11 @@ func TestDecode(t *testing.T) {
{
name: "rejected",
in: hex("c349010000000000000000"), // 3(-18446744073709551617)
fixme: "decoding cbor data tagged with 3 produces big.Int instead of rejecting",
assertOnError: func(t *testing.T, e error) {
// TODO: Once this can pass, make the assertion stronger.
if e == nil {
t.Error("expected non-nil error")
assertOnError: assertOnConcreteError(func(t *testing.T, e *cbor.UnacceptableDataItemError) {
if diff := cmp.Diff(&cbor.UnacceptableDataItemError{CBORType: "tag", Message: "bignum"}, e); diff != "" {
t.Errorf("unexpected error diff:\n%s", diff)
}
},
}),
},
})

View File

@@ -37,11 +37,10 @@ var Encode cbor.EncMode = func() cbor.EncMode {
NaNConvert: cbor.NaNConvertReject,
InfConvert: cbor.InfConvertReject,
// Prefer encoding math/big.Int to one of the 64-bit integer types if it fits. When
// later decoded into Unstructured, the set of allowable concrete numeric types is
// limited to int64 and float64, so the distinction between big integer and integer
// can't be preserved.
BigIntConvert: cbor.BigIntConvertShortest,
// Error on attempt to encode math/big.Int values, which can't be faithfully
// roundtripped through Unstructured in general (the dynamic numeric types allowed
// in Unstructured are limited to float64 and int64).
BigIntConvert: cbor.BigIntConvertReject,
// MarshalJSON for time.Time writes RFC3339 with nanos.
Time: cbor.TimeRFC3339Nano,

View File

@@ -18,6 +18,8 @@ package modes_test
import (
"fmt"
"math/big"
"reflect"
"testing"
"github.com/fxamacker/cbor/v2"
@@ -53,6 +55,15 @@ func TestEncode(t *testing.T) {
want: []byte{0xa1, 0x41, 0x41, 0x02}, // {"A": 2}
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
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) {
out, err := encMode.Marshal(tc.in)
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)
}
})