encoding/protojson: restrict valid values for google.protobuf.Value.number_value

The purpose of struct.proto is to be an exact mapping of JSON in protobufs.
Since JSON doesn't support NaN and Inf, we should reject serialization
of such values. Prior to this CL, they would be serialzed as a JSON string,
which would change the interpretation of the value when round-tripped.

Fixes golang/protobuf#1182

Change-Id: I6dba9973b1c24d99e5688b509611c0a952c00022
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/247737
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Herbie Ong <herbie@google.com>
This commit is contained in:
Joe Tsai 2020-08-10 10:46:34 -07:00
parent 16365ed3d8
commit 0fd4f3a506
2 changed files with 18 additions and 0 deletions

View File

@ -1255,6 +1255,18 @@ func TestMarshal(t *testing.T) {
{},
[]
]`,
}, {
desc: "Value with NaN",
input: structpb.NewNumberValue(math.NaN()),
wantErr: true,
}, {
desc: "Value with -Inf",
input: structpb.NewNumberValue(math.Inf(-1)),
wantErr: true,
}, {
desc: "Value with +Inf",
input: structpb.NewNumberValue(math.Inf(+1)),
wantErr: true,
}, {
desc: "Struct with nil map",
input: &structpb.Struct{},

View File

@ -7,6 +7,7 @@ package protojson
import (
"bytes"
"fmt"
"math"
"strconv"
"strings"
"time"
@ -495,6 +496,11 @@ func (e encoder) marshalKnownValue(m pref.Message) error {
if fd == nil {
return errors.New("%s: none of the oneof fields is set", genid.Value_message_fullname)
}
if fd.Number() == genid.Value_NumberValue_field_number {
if v := m.Get(fd).Float(); math.IsNaN(v) || math.IsInf(v, 0) {
return errors.New("%s: invalid %v value", genid.Value_NumberValue_field_fullname, v)
}
}
return e.marshalSingular(m.Get(fd), fd)
}