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: [email protected]
Reporter: [email protected]
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: [email protected]
For additional commands, e-mail: [email protected]