L1nq0 opened a new issue, #108:
URL: https://github.com/apache/dubbo-hessian-lite/issues/108
While testing hessian-lite 4.0.4 (org.apache.dubbo:hessian-lite from Maven
Central) against short malformed streams, we found that a class definition op
code with a large field count makes the reader allocate arrays sized directly
from that count and throw OutOfMemoryError. The same code is on master today,
and the 4.0.4 line numbers below match master.
Details:
Hessian2Input.readObjectDefinition (4.0.4, line 2919) reads the type name
and the field count from the stream, then allocates two arrays from the count
before reading any field name:
```
String type = readString();
int len = readInt();
...
Object[] fields = reader.createFields(len);
String[] fieldNames = new String[len];
```
createFields in AbstractDeserializer (line 108) is new String[len]. Nothing
compares the count with the remaining input, although each field name takes at
least one byte on the wire, so a count above the remaining input length can
never be satisfied.
The type name does not need to resolve to a real class for this to happen:
an unknown type falls back to a map deserializer and the allocation still runs.
Reproduction:
The class definition op code is 43 ('C'), the type name below is the
one-character string x (01 78), then a raw four-byte field count. The full
stream is eight bytes:
```
43 01 78 49 7f ff ff ff field count 2147483647
43 01 78 49 49 49 49 49 field count 1229539657
```
A minimal runner with nothing but the hessian-lite jar on the classpath:
```java
import com.alibaba.com.caucho.hessian.io.Hessian2Input;
import java.io.ByteArrayInputStream;
import java.util.HexFormat;
public class C2Poc {
public static void main(String[] args) throws Exception {
String hex = args.length > 0 ? args[0] : "430178497fffffff";
Hessian2Input in = new Hessian2Input(new
ByteArrayInputStream(HexFormat.of().parseHex(hex)));
in.readObject();
}
}
```
```
javac -cp hessian-lite-4.0.4.jar C2Poc.java
java -Xmx64m -cp .:hessian-lite-4.0.4.jar C2Poc 430178497fffffff
java -Xmx64m -cp .:hessian-lite-4.0.4.jar C2Poc 4301784949494949
```
Observed on OpenJDK 21.0.12, both inputs fail inside readObject with these
frames:
```
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at
com.alibaba.com.caucho.hessian.io.AbstractDeserializer.createFields(AbstractDeserializer.java:109)
at
com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectDefinition(Hessian2Input.java:2928)
at
com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2855)
```
The second input reports java.lang.OutOfMemoryError: Java heap space
instead, since 1229539657 references request roughly 4.9 GB of heap with
compressed oops. An eight-byte stream turns into a multi-gigabyte allocation
before the first field name is even read.
Suggested fix:
Compare the field count with the remaining input length before allocating. A
class definition cannot carry more field names than it has bytes left, so a
count above the remaining input length can be rejected as a protocol error, the
same way other malformed input is rejected. One comparison after readInt covers
both arrays.
Happy to share the full outputs of the runs or submit a PR adding the check
with tests.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]