aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Tsai <joetsai@digital-static.net>2022-08-25 11:32:03 -0700
committerMichael Stapelberg <stapelberg@google.com>2022-08-31 09:28:52 +0000
commitf930b1dc76e8ff950a69a8bd945562261d045c64 (patch)
tree600d39a39a88ceac5a5eebfe635921338fe2b41e
parent692f4a24f8dc0d375508fc41e657920d411b5b68 (diff)
downloadgolang-protobuf-f930b1dc76e8ff950a69a8bd945562261d045c64.tar.gz
encoding/protojson: fix parsing of google.protobuf.Timestamp
The Timestamp message uses a subset of RFC 3339. RFC 3339, section 5.6 specifies that the subsecond field can have any non-zero number of digits. On the other hand, the protobuf documentation specifies that Timestamp uses RFC 3339 with a few restrictions. In other words, protobuf does NOT use RFC 3339, but rather a subset of it. An upstream change https://go.dev/cl/425037 modifies the time package to be internally consistent about handling of extra subsecond digits allowing it to be more in line with RFC 3339. Make a corresponding change here to ensure we remain compliant with protobuf's restricted use of RFC 3339. Change-Id: Ic145c68492fb41a5f7b79b653f3246dd9091d5d8 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/425554 Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Lasse Folger <lassefolger@google.com>
-rw-r--r--encoding/protojson/well_known_types.go12
1 files changed, 9 insertions, 3 deletions
diff --git a/encoding/protojson/well_known_types.go b/encoding/protojson/well_known_types.go
index c85f8469..6c37d417 100644
--- a/encoding/protojson/well_known_types.go
+++ b/encoding/protojson/well_known_types.go
@@ -814,16 +814,22 @@ func (d decoder) unmarshalTimestamp(m protoreflect.Message) error {
return d.unexpectedTokenError(tok)
}
- t, err := time.Parse(time.RFC3339Nano, tok.ParsedString())
+ s := tok.ParsedString()
+ t, err := time.Parse(time.RFC3339Nano, s)
if err != nil {
return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString())
}
- // Validate seconds. No need to validate nanos because time.Parse would have
- // covered that already.
+ // Validate seconds.
secs := t.Unix()
if secs < minTimestampSeconds || secs > maxTimestampSeconds {
return d.newError(tok.Pos(), "%v value out of range: %v", genid.Timestamp_message_fullname, tok.RawString())
}
+ // Validate subseconds.
+ i := strings.LastIndexByte(s, '.') // start of subsecond field
+ j := strings.LastIndexAny(s, "Z-+") // start of timezone field
+ if i >= 0 && j >= i && j-i > len(".999999999") {
+ return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString())
+ }
fds := m.Descriptor().Fields()
fdSeconds := fds.ByNumber(genid.Timestamp_Seconds_field_number)