VYPR
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.

PackageAffected versionsPatched versions
org.apache.tomcat:tomcatMaven
>= 9.0.0.M1, < 9.0.0.M129.0.0.M12
org.apache.tomcat:tomcatMaven
>= 8.5.0, < 8.5.88.5.8

Affected products

1
  • Apache Software Foundation/Apache Tomcatv5
    Range: 9.0.0.M1 to 9.0.0.M11

Patches

2
85c63227edab

Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=60232

https://github.com/apache/tomcatMark ThomasOct 20, 2016via ghsa
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">
    
079372fc7bac

Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=60232

https://github.com/apache/tomcatMark ThomasOct 20, 2016via ghsa
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

News mentions

0

No linked articles in our index yet.