File: 0001-encoding-protojson-fix-parsing-of-google.protobuf.Ti.patch

package info (click to toggle)
golang-google-protobuf 1.28.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bookworm-backports, bookworm-proposed-updates, sid
  • size: 10,424 kB
  • sloc: sh: 98; makefile: 4
file content (56 lines) | stat: -rw-r--r-- 2,460 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
From: Joe Tsai <joetsai@digital-static.net>
Date: Thu, 25 Aug 2022 11:32:03 -0700
Subject: 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>
---
 encoding/protojson/well_known_types.go | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/encoding/protojson/well_known_types.go b/encoding/protojson/well_known_types.go
index c85f846..6c37d41 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)