Skip to content

Commit e13e9a5

Browse files
committed
[GR-31370] Wasm: Memory allocation failure should not be an internal error.
PullRequest: graal/8940
2 parents d9042de + a158000 commit e13e9a5

File tree

4 files changed

+48
-16
lines changed

4 files changed

+48
-16
lines changed

wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmJsApiSuite.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
import org.junit.Test;
8282

8383
import com.oracle.truffle.api.Truffle;
84+
import com.oracle.truffle.api.exception.AbstractTruffleException;
8485
import com.oracle.truffle.api.frame.VirtualFrame;
8586
import com.oracle.truffle.api.interop.ArityException;
8687
import com.oracle.truffle.api.interop.ExceptionType;
@@ -779,6 +780,20 @@ public void testTableImport() throws IOException, InterruptedException {
779780
});
780781
}
781782

783+
@Test
784+
public void testMemoryAllocationFailure() {
785+
// Memory allocation should either succeed or throw an interop
786+
// exception (not an internal error like OutOfMemoryError).
787+
try {
788+
Object[] memories = new Object[5];
789+
for (int i = 0; i < memories.length; i++) {
790+
memories[i] = Memory.create(new MemoryDescriptor(32767, 32767));
791+
}
792+
} catch (AbstractTruffleException ex) {
793+
Assert.assertTrue("Should throw interop exception", InteropLibrary.getUncached(ex).isException(ex));
794+
}
795+
}
796+
782797
private static void runTest(Consumer<WasmContext> testCase) throws IOException {
783798
final Context.Builder contextBuilder = Context.newBuilder("wasm");
784799
contextBuilder.option("wasm.Builtins", "testutil:testutil");

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/exception/Failure.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ public enum Failure {
122122
MEMORY_INSTANCE_SIZE_LIMIT_EXCEEDED(Type.TRAP, "memory instance size exceeds limit"),
123123

124124
CALL_STACK_EXHAUSTED(Type.EXHAUSTION, "call stack exhausted"),
125+
MEMORY_ALLOCATION_FAILED(Type.EXHAUSTION, "could not allocate memory"),
125126

126127
// TODO(mbovel): replace UNSPECIFIED_INTERNAL usages with assertInternal/shouldNotReachHere.
127128
UNSPECIFIED_INTERNAL(Type.INTERNAL, "unspecified");

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/ByteArrayWasmMemory.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@ private ByteArrayWasmMemory(int declaredMinSize, int declaredMaxSize, int initia
8989
this.declaredMinSize = declaredMinSize;
9090
this.declaredMaxSize = declaredMaxSize;
9191
this.maxAllowedSize = maxAllowedSize;
92-
this.buffer = new byte[initialSize * MEMORY_PAGE_SIZE];
92+
try {
93+
this.buffer = new byte[initialSize * MEMORY_PAGE_SIZE];
94+
} catch (OutOfMemoryError error) {
95+
throw WasmException.create(Failure.MEMORY_ALLOCATION_FAILED);
96+
}
9397
}
9498

9599
public ByteArrayWasmMemory(int declaredMinSize, int declaredMaxSize, int maxAllowedSize) {
@@ -139,13 +143,17 @@ public synchronized boolean grow(int extraPageSize) {
139143
if (extraPageSize == 0) {
140144
return true;
141145
} else if (compareUnsigned(extraPageSize, maxAllowedSize) <= 0 && compareUnsigned(size() + extraPageSize, maxAllowedSize) <= 0) {
142-
// Condition above and limit on maxPageSize (see ModuleLimits#MAX_MEMORY_SIZE) ensure
143-
// computation of targetByteSize does not overflow.
144-
final int targetByteSize = multiplyExact(addExact(size(), extraPageSize), MEMORY_PAGE_SIZE);
145-
final byte[] newBuffer = new byte[targetByteSize];
146-
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
147-
buffer = newBuffer;
148-
return true;
146+
try {
147+
// Condition above and limit on maxPageSize (see ModuleLimits#MAX_MEMORY_SIZE)
148+
// ensure computation of targetByteSize does not overflow.
149+
final int targetByteSize = multiplyExact(addExact(size(), extraPageSize), MEMORY_PAGE_SIZE);
150+
final byte[] newBuffer = new byte[targetByteSize];
151+
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
152+
buffer = newBuffer;
153+
return true;
154+
} catch (OutOfMemoryError error) {
155+
throw WasmException.create(Failure.MEMORY_ALLOCATION_FAILED);
156+
}
149157
} else {
150158
return false;
151159
}

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/UnsafeWasmMemory.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ private UnsafeWasmMemory(int declaredMinSize, int declaredMaxSize, int initialSi
102102
this.size = declaredMinSize;
103103
this.maxAllowedSize = maxAllowedSize;
104104
final long byteSize = byteSize();
105-
this.startAddress = unsafe.allocateMemory(byteSize);
105+
try {
106+
this.startAddress = unsafe.allocateMemory(byteSize);
107+
} catch (OutOfMemoryError error) {
108+
throw WasmException.create(Failure.MEMORY_ALLOCATION_FAILED);
109+
}
106110
unsafe.setMemory(startAddress, byteSize, (byte) 0);
107111
}
108112

@@ -165,13 +169,17 @@ public boolean grow(int extraPageSize) {
165169
// Condition above and limit on maxPageSize (see ModuleLimits#MAX_MEMORY_SIZE) ensure
166170
// computation of targetByteSize does not overflow.
167171
final int targetByteSize = multiplyExact(addExact(size(), extraPageSize), MEMORY_PAGE_SIZE);
168-
final long updatedStartAddress = unsafe.allocateMemory(targetByteSize);
169-
unsafe.copyMemory(startAddress, updatedStartAddress, byteSize());
170-
unsafe.setMemory(updatedStartAddress + byteSize(), targetByteSize - byteSize(), (byte) 0);
171-
unsafe.freeMemory(startAddress);
172-
startAddress = updatedStartAddress;
173-
size += extraPageSize;
174-
return true;
172+
try {
173+
final long updatedStartAddress = unsafe.allocateMemory(targetByteSize);
174+
unsafe.copyMemory(startAddress, updatedStartAddress, byteSize());
175+
unsafe.setMemory(updatedStartAddress + byteSize(), targetByteSize - byteSize(), (byte) 0);
176+
unsafe.freeMemory(startAddress);
177+
startAddress = updatedStartAddress;
178+
size += extraPageSize;
179+
return true;
180+
} catch (OutOfMemoryError error) {
181+
throw WasmException.create(Failure.MEMORY_ALLOCATION_FAILED);
182+
}
175183
} else {
176184
return false;
177185
}

0 commit comments

Comments
 (0)