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

            Bug ID: 65340
           Summary: Hpack decode NegativeArraySizeException: -1
           Product: Tomcat 9
           Version: 9.0.45
          Hardware: PC
                OS: Mac OS X 10.1
            Status: NEW
          Severity: critical
          Priority: P2
         Component: Servlet
          Assignee: dev@tomcat.apache.org
          Reporter: 297442...@qq.com
  Target Milestone: -----

Jetty version
9.4.41.v20210516
Java version
JDK1.8
Tomcat version
9.0.45

Question
1: when jetty cllient hpack index all of http2 header,found tomcat will throw
some exception like this:

An exception has been raised by Name:http-nio-9315-exec-159,Id:440
java.lang.RuntimeException: java.lang.NegativeArraySizeException: -1
 at org.apache.coyote.http2.HpackDecoder.decode(HpackDecoder.java:130)
 at org.apache.coyote.http2.Http2Parser.readHeaderPayload(Http2Parser.java:486)
 at org.apache.coyote.http2.Http2Parser.readHeadersFrame(Http2Parser.java:270)
 at
org.apache.coyote.http2.Http2AsyncParser$FrameCompletionHandler.completed(Http2AsyncParser.java:251)
 at
org.apache.coyote.http2.Http2AsyncParser$FrameCompletionHandler.completed(Http2AsyncParser.java:164)
 at
org.apache.tomcat.util.net.SocketWrapperBase$VectoredIOCompletionHandler.completed(SocketWrapperBase.java:1089)
 at
org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper$NioOperationState.run(NioEndpoint.java:1621)
 at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
 at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
 at
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
 at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.NegativeArraySizeException: -1
 at
java.base/java.lang.AbstractStringBuilder.<init>(AbstractStringBuilder.java:86)
 at java.base/java.lang.StringBuilder.<init>(StringBuilder.java:112)
 at
org.apache.coyote.http2.HpackDecoder.readHuffmanString(HpackDecoder.java:261)
 at org.apache.coyote.http2.HpackDecoder.readHpackString(HpackDecoder.java:251)
 at org.apache.coyote.http2.HpackDecoder.decode(HpackDecoder.java:126)
 ... 10 more

2: so replace tomcat HpackDecoder code in project class to catch error like
this:

 void decode(ByteBuffer buffer) throws HpackException {
        while (buffer.hasRemaining()) {
            int originalPos = buffer.position();
            byte b = buffer.get();
            if ((b & 0b10000000) != 0) {
                //if the first bit is set it is an indexed header field
                buffer.position(buffer.position() - 1); //unget the byte
                int index = Hpack.decodeInteger(buffer, 7); //prefix is 7
                if (index == -1) {
                    buffer.position(originalPos);
                    return;
                } else if(index == 0) {
                    throw new HpackException(
                           
sm.getString("hpackdecoder.zeroNotValidHeaderTableIndex"));
                }
                handleIndex(index);
            } else if ((b & 0b01000000) != 0) {
                //Literal Header Field with Incremental Indexing
                String headerName = readHeaderName(buffer, 6);
                if (headerName == null) {
                    buffer.position(originalPos);
                    return;
                }
                String headerValue = null;
                ByteBuffer bufferReplica = buffer.duplicate();
                try {
                    headerValue = readHpackString(buffer);
                } catch (Throwable e) {
                    CharBuffer originalValue =
StandardCharsets.UTF_8.decode(bufferReplica);
                    // **log decode error header** 
                    log.warn("hpack decode error, headerName: {}, value: {}",
headerName, originalValue);
                    throw new RuntimeException(e);
                }
                if (headerValue == null) {
                    buffer.position(originalPos);
                    return;
                }
                emitHeader(headerName, headerValue);
                addEntryToHeaderTable(new Hpack.HeaderField(headerName,
headerValue));
            } else if ((b & 0b11110000) == 0) {
                //Literal Header Field without Indexing
                String headerName = readHeaderName(buffer, 4);
                if (headerName == null) {
                    buffer.position(originalPos);
                    return;
                }
                String headerValue = null;
                ByteBuffer bufferReplica = buffer.duplicate();
                try {
                    headerValue = readHpackString(buffer);
                } catch (Throwable e) {
                    CharBuffer originalValue =
StandardCharsets.UTF_8.decode(bufferReplica);
                    **log.warn("hpack decode error, headerName: {}, value: {}",
headerName, originalValue);**
                    throw new RuntimeException(e);
                }
                if (headerValue == null) {
                    buffer.position(originalPos);
                    return;
                }
                emitHeader(headerName, headerValue);
            } else if ((b & 0b11110000) == 0b00010000) {
                //Literal Header Field never indexed
                String headerName = readHeaderName(buffer, 4);
                if (headerName == null) {
                    buffer.position(originalPos);
                    return;
                }
                String headerValue = null;
                ByteBuffer bufferReplica = buffer.duplicate();
                try {
                    headerValue = readHpackString(buffer);
                } catch (Throwable e) {
                    CharBuffer originalValue =
StandardCharsets.UTF_8.decode(bufferReplica);
                    log.warn("hpack decode error, headerName: {}, value: {}",
headerName, originalValue);
                    throw new RuntimeException(e);
                }
                if (headerValue == null) {
                    buffer.position(originalPos);
                    return;
                }
                emitHeader(headerName, headerValue);
            } else if ((b & 0b11100000) == 0b00100000) {
                //context update max table size change
                if (!handleMaxMemorySizeChange(buffer, originalPos)) {
                    return;
                }
            } else {
                throw new
RuntimeException(sm.getString("hpackdecoder.notImplemented"));
            }
        }
    }



https://github.com/eclipse/jetty.project/issues/6333

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to