High severity7.5NVD Advisory· Published Aug 10, 2017· Updated May 13, 2026
CVE-2016-6817
CVE-2016-6817
Description
The HTTP/2 header parser in Apache Tomcat 9.0.0.M1 to 9.0.0.M11 and 8.5.0 to 8.5.6 entered an infinite loop if a header was received that was larger than the available buffer. This made a denial of service attack possible.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.tomcat:tomcatMaven | >= 9.0.0.M1, < 9.0.0.M12 | 9.0.0.M12 |
org.apache.tomcat:tomcatMaven | >= 8.5.0, < 8.5.8 | 8.5.8 |
Affected products
1- Apache Software Foundation/Apache Tomcatv5Range: 9.0.0.M1 to 9.0.0.M11
Patches
285c63227edabFix https://bz.apache.org/bugzilla/show_bug.cgi?id=60232
3 files changed · +35 −4
java/org/apache/coyote/http2/Constants.java+3 −0 modified@@ -20,4 +20,7 @@ public class Constants { // Prioritisation public static final int DEFAULT_WEIGHT = 16; + + // Parsing + static final int DEFAULT_HEADER_READ_BUFFER_SIZE = 1024; }
java/org/apache/coyote/http2/Http2Parser.java+27 −4 modified@@ -24,6 +24,7 @@ import org.apache.coyote.http2.HpackDecoder.HeaderEmitter; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.buf.ByteBufferUtils; import org.apache.tomcat.util.res.StringManager; class Http2Parser { @@ -40,7 +41,8 @@ class Http2Parser { private final byte[] frameHeaderBuffer = new byte[9]; private volatile HpackDecoder hpackDecoder; - private final ByteBuffer headerReadBuffer = ByteBuffer.allocate(1024); + private volatile ByteBuffer headerReadBuffer = + ByteBuffer.allocate(Constants.DEFAULT_HEADER_READ_BUFFER_SIZE); private volatile int headersCurrentStream = -1; private volatile boolean headersEndStream = false; @@ -380,8 +382,24 @@ private void readContinuationFrame(int streamId, int flags, int payloadSize) private void readHeaderPayload(int payloadSize) throws Http2Exception, IOException { - while (payloadSize > 0) { - int toRead = Math.min(headerReadBuffer.remaining(), payloadSize); + int remaining = payloadSize; + + while (remaining > 0) { + if (headerReadBuffer.remaining() == 0) { + // Buffer needs expansion + int newSize; + if (headerReadBuffer.capacity() < payloadSize) { + // First step, expand to the current payload. That should + // cover most cases. + newSize = payloadSize; + } else { + // Header must be spread over multiple frames. Keep doubling + // buffer size until the header can be read. + newSize = headerReadBuffer.capacity() * 2; + } + headerReadBuffer = ByteBufferUtils.expand(headerReadBuffer, newSize); + } + int toRead = Math.min(headerReadBuffer.remaining(), remaining); // headerReadBuffer in write mode input.fill(true, headerReadBuffer, toRead); // switch to read mode @@ -395,7 +413,7 @@ private void readHeaderPayload(int payloadSize) throws Http2Exception, IOExcepti } // switches to write mode headerReadBuffer.compact(); - payloadSize -= toRead; + remaining -= toRead; } hpackDecoder.getHeaderEmitter().validateHeaders(); @@ -416,6 +434,11 @@ private void onHeadersComplete(int streamId) throws Http2Exception { output.receivedEndOfStream(streamId); headersEndStream = false; } + + // Reset size for new request if the buffer was previously expanded + if (headerReadBuffer.capacity() > Constants.DEFAULT_HEADER_READ_BUFFER_SIZE) { + headerReadBuffer = ByteBuffer.allocate(Constants.DEFAULT_HEADER_READ_BUFFER_SIZE); + } }
webapps/docs/changelog.xml+5 −0 modified@@ -104,6 +104,11 @@ <add> Add support for trailer headers to the HTTP/2 implementation. (markt) </add> + <fix> + <bug>60232</bug>: When processing headers for an HTTP/2 stream, ensure + that the read buffer is large enough for the header being processed. + (markt) + </fix> </changelog> </subsection> <subsection name="Jasper">
079372fc7bacFix https://bz.apache.org/bugzilla/show_bug.cgi?id=60232
3 files changed · +35 −4
java/org/apache/coyote/http2/Constants.java+3 −0 modified@@ -20,4 +20,7 @@ public class Constants { // Prioritisation public static final int DEFAULT_WEIGHT = 16; + + // Parsing + static final int DEFAULT_HEADER_READ_BUFFER_SIZE = 1024; }
java/org/apache/coyote/http2/Http2Parser.java+27 −4 modified@@ -24,6 +24,7 @@ import org.apache.coyote.http2.HpackDecoder.HeaderEmitter; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.buf.ByteBufferUtils; import org.apache.tomcat.util.res.StringManager; class Http2Parser { @@ -40,7 +41,8 @@ class Http2Parser { private final byte[] frameHeaderBuffer = new byte[9]; private volatile HpackDecoder hpackDecoder; - private final ByteBuffer headerReadBuffer = ByteBuffer.allocate(1024); + private volatile ByteBuffer headerReadBuffer = + ByteBuffer.allocate(Constants.DEFAULT_HEADER_READ_BUFFER_SIZE); private volatile int headersCurrentStream = -1; private volatile boolean headersEndStream = false; @@ -380,8 +382,24 @@ private void readContinuationFrame(int streamId, int flags, int payloadSize) private void readHeaderPayload(int payloadSize) throws Http2Exception, IOException { - while (payloadSize > 0) { - int toRead = Math.min(headerReadBuffer.remaining(), payloadSize); + int remaining = payloadSize; + + while (remaining > 0) { + if (headerReadBuffer.remaining() == 0) { + // Buffer needs expansion + int newSize; + if (headerReadBuffer.capacity() < payloadSize) { + // First step, expand to the current payload. That should + // cover most cases. + newSize = payloadSize; + } else { + // Header must be spread over multiple frames. Keep doubling + // buffer size until the header can be read. + newSize = headerReadBuffer.capacity() * 2; + } + headerReadBuffer = ByteBufferUtils.expand(headerReadBuffer, newSize); + } + int toRead = Math.min(headerReadBuffer.remaining(), remaining); // headerReadBuffer in write mode input.fill(true, headerReadBuffer, toRead); // switch to read mode @@ -395,7 +413,7 @@ private void readHeaderPayload(int payloadSize) throws Http2Exception, IOExcepti } // switches to write mode headerReadBuffer.compact(); - payloadSize -= toRead; + remaining -= toRead; } hpackDecoder.getHeaderEmitter().validateHeaders(); @@ -416,6 +434,11 @@ private void onHeadersComplete(int streamId) throws Http2Exception { output.receivedEndOfStream(streamId); headersEndStream = false; } + + // Reset size for new request if the buffer was previously expanded + if (headerReadBuffer.capacity() > Constants.DEFAULT_HEADER_READ_BUFFER_SIZE) { + headerReadBuffer = ByteBuffer.allocate(Constants.DEFAULT_HEADER_READ_BUFFER_SIZE); + } }
webapps/docs/changelog.xml+5 −0 modified@@ -117,6 +117,11 @@ <add> Add support for trailer headers to the HTTP/2 implementation. (markt) </add> + <fix> + <bug>60232</bug>: When processing headers for an HTTP/2 stream, ensure + that the read buffer is large enough for the header being processed. + (markt) + </fix> </changelog> </subsection> <subsection name="Jasper">
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
20- www.securityfocus.com/bid/94462nvdThird Party AdvisoryVDB EntryWEB
- www.securitytracker.com/id/1037330nvdThird Party AdvisoryVDB EntryWEB
- github.com/advisories/GHSA-698c-2x4j-g9gqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2016-6817ghsaADVISORY
- github.com/apache/tomcat/commit/079372fc7bac8e2e378942715c9ce26a4a72c07aghsaWEB
- github.com/apache/tomcat/commit/85c63227edabbfb4f2f500fc557480a190135d21ghsaWEB
- lists.apache.org/thread.html/343558d982879bf88ec20dbf707f8c11255f8e219e81d45c4f8d0551%40%3Cdev.tomcat.apache.org%3EnvdWEB
- lists.apache.org/thread.html/343558d982879bf88ec20dbf707f8c11255f8e219e81d45c4f8d0551@%3Cdev.tomcat.apache.org%3EghsaWEB
- lists.apache.org/thread.html/6af47120905aa7d8fe12f42e8ff2284fb338ba141d3b77b8c7cb61b3%40%3Cdev.tomcat.apache.org%3EnvdWEB
- lists.apache.org/thread.html/6af47120905aa7d8fe12f42e8ff2284fb338ba141d3b77b8c7cb61b3@%3Cdev.tomcat.apache.org%3EghsaWEB
- lists.apache.org/thread.html/88855876c33f2f9c532ffb75bfee570ccf0b17ffa77493745af9a17a%40%3Cdev.tomcat.apache.org%3EnvdWEB
- lists.apache.org/thread.html/88855876c33f2f9c532ffb75bfee570ccf0b17ffa77493745af9a17a@%3Cdev.tomcat.apache.org%3EghsaWEB
- lists.apache.org/thread.html/a9f24571460af003071475b75f18cad81ebcc36fa7c876965a75e32a%40%3Cannounce.tomcat.apache.org%3EnvdWEB
- lists.apache.org/thread.html/a9f24571460af003071475b75f18cad81ebcc36fa7c876965a75e32a@%3Cannounce.tomcat.apache.org%3EghsaWEB
- lists.apache.org/thread.html/b5e3f51d28cd5d9b1809f56594f2cf63dcd6a90429e16ea9f83bbedc%40%3Cdev.tomcat.apache.org%3EnvdWEB
- lists.apache.org/thread.html/b5e3f51d28cd5d9b1809f56594f2cf63dcd6a90429e16ea9f83bbedc@%3Cdev.tomcat.apache.org%3EghsaWEB
- security.netapp.com/advisory/ntap-20180607-0001ghsaWEB
- web.archive.org/web/20180115024458/http://www.securitytracker.com/id/1037330ghsaWEB
- web.archive.org/web/20200227174145/http://www.securityfocus.com/bid/94462ghsaWEB
- security.netapp.com/advisory/ntap-20180607-0001/nvd
News mentions
0No linked articles in our index yet.