Skip to content

Commit fe2abcb

Browse files
committed
quic: validate stream limits in transport params
The maximum number of streams of a given type (bidi/uni) is capped to 2^60, since a larger number would overflow a varint. Validate limits received in transport parameters. RFC 9000, Section 4.6 For golang/go#58547 Change-Id: I7a4a15c569da91ad1b89a5dc71e1c5b213dbda9a Reviewed-on: https://go-review.googlesource.com/c/net/+/524037 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Jonathan Amsterdam <[email protected]>
1 parent d1b0a97 commit fe2abcb

File tree

5 files changed

+27
-3
lines changed

5 files changed

+27
-3
lines changed

internal/quic/packet_parser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ func consumeMaxStreamsFrame(b []byte) (typ streamType, max int64, n int) {
378378
return 0, 0, -1
379379
}
380380
n += nn
381-
if v > 1<<60 {
381+
if v > maxStreamsLimit {
382382
return 0, 0, -1
383383
}
384384
return typ, int64(v), n

internal/quic/quic.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ const timerGranularity = 1 * time.Millisecond
5555
// https://www.rfc-editor.org/rfc/rfc9000#section-14.1
5656
const minimumClientInitialDatagramSize = 1200
5757

58+
// Maximum number of streams of a given type which may be created.
59+
// https://www.rfc-editor.org/rfc/rfc9000.html#section-4.6-2
60+
const maxStreamsLimit = 1 << 60
61+
5862
// A connSide distinguishes between the client and server sides of a connection.
5963
type connSide int8
6064

internal/quic/stream_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,8 +1165,8 @@ func newTestConnAndRemoteStream(t *testing.T, side connSide, styp streamType, op
11651165

11661166
// permissiveTransportParameters may be passed as an option to newTestConn.
11671167
func permissiveTransportParameters(p *transportParameters) {
1168-
p.initialMaxStreamsBidi = maxVarint
1169-
p.initialMaxStreamsUni = maxVarint
1168+
p.initialMaxStreamsBidi = maxStreamsLimit
1169+
p.initialMaxStreamsUni = maxStreamsLimit
11701170
p.initialMaxData = maxVarint
11711171
p.initialMaxStreamDataBidiRemote = maxVarint
11721172
p.initialMaxStreamDataBidiLocal = maxVarint

internal/quic/transport_params.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,14 @@ func unmarshalTransportParams(params []byte) (transportParameters, error) {
212212
p.initialMaxStreamDataUni, n = consumeVarintInt64(val)
213213
case paramInitialMaxStreamsBidi:
214214
p.initialMaxStreamsBidi, n = consumeVarintInt64(val)
215+
if p.initialMaxStreamsBidi > maxStreamsLimit {
216+
return p, localTransportError(errTransportParameter)
217+
}
215218
case paramInitialMaxStreamsUni:
216219
p.initialMaxStreamsUni, n = consumeVarintInt64(val)
220+
if p.initialMaxStreamsUni > maxStreamsLimit {
221+
return p, localTransportError(errTransportParameter)
222+
}
217223
case paramAckDelayExponent:
218224
var v uint64
219225
v, n = consumeVarint(val)

internal/quic/transport_params_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,20 @@ func TestTransportParametersErrors(t *testing.T) {
236236
15, // length
237237
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
238238
},
239+
}, {
240+
desc: "initial_max_streams_bidi is too large",
241+
enc: []byte{
242+
0x08, // initial_max_streams_bidi,
243+
8, // length,
244+
0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
245+
},
246+
}, {
247+
desc: "initial_max_streams_uni is too large",
248+
enc: []byte{
249+
0x08, // initial_max_streams_uni,
250+
9, // length,
251+
0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
252+
},
239253
}, {
240254
desc: "preferred_address is too short",
241255
enc: []byte{

0 commit comments

Comments
 (0)