Author: markt Date: Thu Nov 16 10:14:39 2017 New Revision: 1815429 URL: http://svn.apache.org/viewvc?rev=1815429&view=rev Log: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=61682 When re-prioritising HTTP/2 streams, ensure that both parent and children fields are correctly updated to avoid a possible StackOverflowError
Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java tomcat/trunk/java/org/apache/coyote/http2/Stream.java tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java?rev=1815429&r1=1815428&r2=1815429&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Thu Nov 16 10:14:39 2017 @@ -1108,6 +1108,7 @@ class Http2UpgradeHandler extends Abstra } } streamToRemove.detachFromParent(); + streamToRemove.getChildStreams().clear(); } Modified: tomcat/trunk/java/org/apache/coyote/http2/Stream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Stream.java?rev=1815429&r1=1815428&r2=1815429&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Thu Nov 16 10:14:39 2017 @@ -87,7 +87,7 @@ class Stream extends AbstractStream impl Stream(Integer identifier, Http2UpgradeHandler handler, Request coyoteRequest) { super(identifier); this.handler = handler; - setParentStream(handler); + handler.addChild(this); setWindowSize(handler.getRemoteSettings().getInitialWindowSize()); state = new StreamStateMachine(this); if (coyoteRequest == null) { @@ -139,6 +139,7 @@ class Stream extends AbstractStream impl this.addChild(parentsChild); } } + detachFromParent(); parent.addChild(this); this.weight = weight; } Modified: tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java?rev=1815429&r1=1815428&r2=1815429&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java (original) +++ tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java Thu Nov 16 10:14:39 2017 @@ -243,7 +243,44 @@ public class TestAbstractStream { Assert.assertTrue(e.getChildStreams().contains(f)); Assert.assertEquals(1, f.getChildStreams().size()); Assert.assertTrue(f.getChildStreams().contains(a)); - } + + // https://bz.apache.org/bugzilla/show_bug.cgi?id=61682 + @Test + public void testCircular03() { + // Setup + Http2UpgradeHandler handler = new Http2UpgradeHandler(new Http2Protocol(), null, null); + Stream a = new Stream(Integer.valueOf(1), handler); + Stream b = new Stream(Integer.valueOf(3), handler); + Stream c = new Stream(Integer.valueOf(5), handler); + Stream d = new Stream(Integer.valueOf(7), handler); + + // Action + b.rePrioritise(a, false, 16); + c.rePrioritise(a, false, 16); + d.rePrioritise(b, false, 16); + c.rePrioritise(handler, false, 16); + a.rePrioritise(c, false, 16); + + // Check parents + Assert.assertEquals(c, a.getParentStream()); + Assert.assertEquals(a, b.getParentStream()); + Assert.assertEquals(handler, c.getParentStream()); + Assert.assertEquals(b, d.getParentStream()); + + // This triggers the StackOverflowError + c.isDescendant(d); + + // Check children + Assert.assertEquals(1, handler.getChildStreams().size()); + Assert.assertTrue(handler.getChildStreams().contains(c)); + Assert.assertEquals(1, c.getChildStreams().size()); + Assert.assertTrue(c.getChildStreams().contains(a)); + Assert.assertEquals(1, a.getChildStreams().size()); + Assert.assertTrue(a.getChildStreams().contains(b)); + Assert.assertEquals(1, b.getChildStreams().size()); + Assert.assertTrue(b.getChildStreams().contains(d)); + Assert.assertEquals(0, d.getChildStreams().size()); + } } Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1815429&r1=1815428&r2=1815429&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Thu Nov 16 10:14:39 2017 @@ -68,6 +68,11 @@ ensure that an HTTP session exists when initiating a WebSocket connection. Patch provided by isapir. (markt) </add> + <fix> + <bug>61682</bug>: When re-prioritising HTTP/2 streams, ensure that both + parent and children fields are correctly updated to avoid a possible + <code>StackOverflowError</code>. (markt) + </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org