Skip to content

Commit 65dfc08

Browse files
tomberganbradfitz
authored andcommitted
http2: reject stream self-dependencies
Fix spec bug: Section 5.3.1 says that self-dependencies should be treated as a stream error of type PROTOCOL_ERROR. Updates golang/go#16046 Change-Id: I8b5dc8808943dc96aac0c543c7032fa989ab9e0b Reviewed-on: https://go-review.googlesource.com/31858 Reviewed-by: Brad Fitzpatrick <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent e7b1435 commit 65dfc08

File tree

2 files changed

+56
-3
lines changed

2 files changed

+56
-3
lines changed

http2/server.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,9 +1473,6 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
14731473

14741474
sc.streams[id] = st
14751475
sc.writeSched.OpenStream(st.id, OpenStreamOptions{})
1476-
if f.HasPriority() {
1477-
sc.writeSched.AdjustStream(st.id, f.Priority)
1478-
}
14791476
sc.curOpenStreams++
14801477
if sc.curOpenStreams == 1 {
14811478
sc.setConnState(http.StateActive)
@@ -1498,6 +1495,12 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
14981495
// runtime.
14991496
return streamError(st.id, ErrCodeRefusedStream)
15001497
}
1498+
if f.HasPriority() {
1499+
if err := checkPriority(f.StreamID, f.Priority); err != nil {
1500+
return err
1501+
}
1502+
sc.writeSched.AdjustStream(st.id, f.Priority)
1503+
}
15011504

15021505
rw, req, err := sc.newWriterAndRequest(st, f)
15031506
if err != nil {
@@ -1565,10 +1568,24 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
15651568
return nil
15661569
}
15671570

1571+
func checkPriority(streamID uint32, p PriorityParam) error {
1572+
if streamID == p.StreamDep {
1573+
// Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
1574+
// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
1575+
// Section 5.3.3 says that a stream can depend on one of its dependencies,
1576+
// so it's only self-dependencies that are forbidden.
1577+
return streamError(streamID, ErrCodeProtocol)
1578+
}
1579+
return nil
1580+
}
1581+
15681582
func (sc *serverConn) processPriority(f *PriorityFrame) error {
15691583
if sc.inGoAway {
15701584
return nil
15711585
}
1586+
if err := checkPriority(f.StreamID, f.PriorityParam); err != nil {
1587+
return err
1588+
}
15721589
sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
15731590
return nil
15741591
}

http2/server_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,12 @@ func (st *serverTester) writeHeaders(p HeadersFrameParam) {
256256
}
257257
}
258258

259+
func (st *serverTester) writePriority(id uint32, p PriorityParam) {
260+
if err := st.fr.WritePriority(id, p); err != nil {
261+
st.t.Fatalf("Error writing PRIORITY: %v", err)
262+
}
263+
}
264+
259265
func (st *serverTester) encodeHeaderField(k, v string) {
260266
err := st.hpackEnc.WriteField(hpack.HeaderField{Name: k, Value: v})
261267
if err != nil {
@@ -1481,6 +1487,36 @@ func TestServer_Rejects_Continuation0(t *testing.T) {
14811487
})
14821488
}
14831489

1490+
// No PRIORITY on stream 0.
1491+
func TestServer_Rejects_Priority0(t *testing.T) {
1492+
testServerRejectsConn(t, func(st *serverTester) {
1493+
st.fr.AllowIllegalWrites = true
1494+
st.writePriority(0, PriorityParam{StreamDep: 1})
1495+
})
1496+
}
1497+
1498+
// No HEADERS frame with a self-dependence.
1499+
func TestServer_Rejects_HeadersSelfDependence(t *testing.T) {
1500+
testServerRejectsStream(t, ErrCodeProtocol, func(st *serverTester) {
1501+
st.fr.AllowIllegalWrites = true
1502+
st.writeHeaders(HeadersFrameParam{
1503+
StreamID: 1,
1504+
BlockFragment: st.encodeHeader(),
1505+
EndStream: true,
1506+
EndHeaders: true,
1507+
Priority: PriorityParam{StreamDep: 1},
1508+
})
1509+
})
1510+
}
1511+
1512+
// No PRIORTY frame with a self-dependence.
1513+
func TestServer_Rejects_PrioritySelfDependence(t *testing.T) {
1514+
testServerRejectsStream(t, ErrCodeProtocol, func(st *serverTester) {
1515+
st.fr.AllowIllegalWrites = true
1516+
st.writePriority(1, PriorityParam{StreamDep: 1})
1517+
})
1518+
}
1519+
14841520
func TestServer_Rejects_PushPromise(t *testing.T) {
14851521
testServerRejectsConn(t, func(st *serverTester) {
14861522
pp := PushPromiseParam{

0 commit comments

Comments
 (0)