diff --git a/arshal_default.go b/arshal_default.go index 8af284b..3bc580b 100644 --- a/arshal_default.go +++ b/arshal_default.go @@ -389,7 +389,7 @@ func makeBytesArshaler(t reflect.Type, fncs *arshaler) *arshaler { if err != nil { return newUnmarshalErrorAfter(dec, t, err) } - if len(val) != encodedLen(len(b)) { + if len(val) != encodedLen(len(b)) && !uo.Flags.Get(jsonflags.FormatBytesWithLegacySemantics) { // TODO(https://go.dev/issue/53845): RFC 4648, section 3.3, // specifies that non-alphabet characters must be rejected. // Unfortunately, the "base32" and "base64" packages allow @@ -402,7 +402,7 @@ func makeBytesArshaler(t reflect.Type, fncs *arshaler) *arshaler { if va.Kind() == reflect.Array { dst := va.Bytes() clear(dst[copy(dst, b):]) // noop if len(b) <= len(dst) - if len(b) != len(dst) { + if len(b) != len(dst) && !uo.Flags.Get(jsonflags.UnmarshalArrayFromAnyLength) { err := fmt.Errorf("decoded length of %d mismatches array length of %d", len(b), len(dst)) return newUnmarshalErrorAfter(dec, t, err) } diff --git a/arshal_test.go b/arshal_test.go index 0f67651..19e42bd 100644 --- a/arshal_test.go +++ b/arshal_test.go @@ -4856,12 +4856,24 @@ func TestUnmarshal(t *testing.T) { inVal: new([2]byte), want: addr([2]byte{1, 0}), wantErr: EU(errors.New("decoded length of 1 mismatches array length of 2")).withType('"', T[[2]byte]()), + }, { + name: jsontest.Name("Bytes/ByteArray2/Underflow/Allowed"), + opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1}, + inBuf: `"AQ=="`, + inVal: new([2]byte), + want: addr([2]byte{1, 0}), }, { name: jsontest.Name("Bytes/ByteArray2/Overflow"), inBuf: `"AQID"`, inVal: new([2]byte), want: addr([2]byte{1, 2}), wantErr: EU(errors.New("decoded length of 3 mismatches array length of 2")).withType('"', T[[2]byte]()), + }, { + name: jsontest.Name("Bytes/ByteArray2/Overflow/Allowed"), + opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1}, + inBuf: `"AQID"`, + inVal: new([2]byte), + want: addr([2]byte{1, 2}), }, { name: jsontest.Name("Bytes/ByteArray3/Valid"), inBuf: `"AQID"`, @@ -6386,6 +6398,12 @@ func TestUnmarshal(t *testing.T) { inBuf: `{"Base64": "aa=\r="}`, inVal: new(structFormatBytes), wantErr: EU(errors.New("illegal character '\\r' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()), + }, { + name: jsontest.Name("Structs/Format/Bytes/Base64/NonAlphabet/Ignored"), + opts: []Options{jsonflags.FormatBytesWithLegacySemantics | 1}, + inBuf: `{"Base64": "aa=\r\n="}`, + inVal: new(structFormatBytes), + want: &structFormatBytes{Base64: []byte{105}}, }, { name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/Space"), inBuf: `{"Base64": "aa= ="}`, diff --git a/v1/options.go b/v1/options.go index e554d03..23094ea 100644 --- a/v1/options.go +++ b/v1/options.go @@ -151,6 +151,12 @@ func EscapeInvalidUTF8(v bool) Options { // In contrast, the v2 default is to report an error unmarshaling // a JSON array when expecting some form of binary data encoding. // +// - When unmarshaling, '\r' and '\n' characters are ignored +// within the encoded "base32" and "base64" data. +// In contrast, the v2 default is to report an error in order to be +// strictly compliant with RFC 4648, section 3.3, +// which specifies that non-alphabet characters must be rejected. +// // This affects either marshaling or unmarshaling. // The v1 default is true. func FormatBytesWithLegacySemantics(v bool) Options {