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