Browse Source

encoding/jsonpb: fix parsing of number strings containing leading/trailing spaces

Per conformance tests, number strings that contain leading or trailing
spaces are not allowed.

https://github.com/protocolbuffers/protobuf/blob/3a3956e8a258784461270961c6577341356bce52/conformance/binary_json_conformance_suite.cc#L1196-L1203

Change-Id: Ifbe0e4ee125fac3c291b456eece541353025cdd4
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/173664
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Herbie Ong 6 years ago
parent
commit
06a6b0bda8
2 changed files with 33 additions and 2 deletions
  1. 13 2
      encoding/jsonpb/decode.go
  2. 20 0
      encoding/jsonpb/decode_test.go

+ 13 - 2
encoding/jsonpb/decode.go

@@ -376,7 +376,11 @@ func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
 
 	case json.String:
 		// Decode number from string.
-		dec := json.NewDecoder([]byte(jval.String()))
+		s := strings.TrimSpace(jval.String())
+		if len(s) != len(jval.String()) {
+			return pref.Value{}, errors.New("invalid number %v", jval.Raw())
+		}
+		dec := json.NewDecoder([]byte(s))
 		var nerr errors.NonFatal
 		jval, err := dec.Read()
 		if !nerr.Merge(err) {
@@ -405,7 +409,11 @@ func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
 
 	case json.String:
 		// Decode number from string.
-		dec := json.NewDecoder([]byte(jval.String()))
+		s := strings.TrimSpace(jval.String())
+		if len(s) != len(jval.String()) {
+			return pref.Value{}, errors.New("invalid number %v", jval.Raw())
+		}
+		dec := json.NewDecoder([]byte(s))
 		var nerr errors.NonFatal
 		jval, err := dec.Read()
 		if !nerr.Merge(err) {
@@ -452,6 +460,9 @@ func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
 			return pref.ValueOf(math.Inf(-1)), nil
 		}
 		// Decode number from string.
+		if len(s) != len(strings.TrimSpace(s)) {
+			return pref.Value{}, errors.New("invalid number %v", jval.Raw())
+		}
 		dec := json.NewDecoder([]byte(s))
 		var nerr errors.NonFatal
 		jval, err := dec.Read()

+ 20 - 0
encoding/jsonpb/decode_test.go

@@ -252,6 +252,16 @@ func TestUnmarshal(t *testing.T) {
 			SFloat:  float32(math.Inf(+1)),
 			SDouble: math.Inf(-1),
 		},
+	}, {
+		desc:         "float string with leading space",
+		inputMessage: &pb3.Scalars{},
+		inputText:    `{"sFloat": " 1.234"}`,
+		wantErr:      true,
+	}, {
+		desc:         "double string with trailing space",
+		inputMessage: &pb3.Scalars{},
+		inputText:    `{"sDouble": "5.678 "}`,
+		wantErr:      true,
 	}, {
 		desc:         "not float",
 		inputMessage: &pb3.Scalars{},
@@ -323,6 +333,16 @@ func TestUnmarshal(t *testing.T) {
 		wantMessage: &pb3.Scalars{
 			SInt32: 12,
 		},
+	}, {
+		desc:         "integer string with leading space",
+		inputMessage: &pb3.Scalars{},
+		inputText:    `{"sInt32": " 1234"}`,
+		wantErr:      true,
+	}, {
+		desc:         "integer string with trailing space",
+		inputMessage: &pb3.Scalars{},
+		inputText:    `{"sUint32": "1e2 "}`,
+		wantErr:      true,
 	}, {
 		desc:         "number is not an integer",
 		inputMessage: &pb3.Scalars{},