Skip to content

Commit b2d393d

Browse files
committed
Throw IndexError on out-of-bounds buffer access
1 parent df23fd9 commit b2d393d

File tree

3 files changed

+61
-16
lines changed

3 files changed

+61
-16
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/BufferStorageNodes.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.common;
4242

43+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.IndexError;
4344
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.OverflowError;
4445
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
4546
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ValueError;
@@ -344,8 +345,15 @@ static void doBytes(PBytesLike src, int srcPos, byte[] dest, int destPos, int le
344345
}
345346

346347
@Specialization
347-
static void doArray(PArray src, int srcPos, byte[] dest, int destPos, int length) {
348-
PythonUtils.arraycopy(src.getBuffer(), srcPos, dest, destPos, length);
348+
static void doArray(PArray src, int srcPos, byte[] dest, int destPos, int length,
349+
@Cached PRaiseNode raiseNode) {
350+
try {
351+
PythonUtils.arraycopy(src.getBuffer(), srcPos, dest, destPos, length);
352+
} catch (ArrayIndexOutOfBoundsException e) {
353+
CompilerDirectives.transferToInterpreterAndInvalidate();
354+
// This can happen when the array gets resized while being exported
355+
throw raiseNode.raise(IndexError, ErrorMessages.INVALID_BUFFER_ACCESS);
356+
}
349357
}
350358
}
351359

@@ -361,8 +369,15 @@ static void doBytes(byte[] src, int srcPos, PBytesLike dest, int destPos, int le
361369
}
362370

363371
@Specialization
364-
static void doArray(byte[] src, int srcPos, PArray dest, int destPos, int length) {
365-
PythonUtils.arraycopy(src, srcPos, dest.getBuffer(), destPos, length);
372+
static void doArray(byte[] src, int srcPos, PArray dest, int destPos, int length,
373+
@Cached PRaiseNode raiseNode) {
374+
try {
375+
PythonUtils.arraycopy(src, srcPos, dest.getBuffer(), destPos, length);
376+
} catch (ArrayIndexOutOfBoundsException e) {
377+
CompilerDirectives.transferToInterpreterAndInvalidate();
378+
// This can happen when the array gets resized while being exported
379+
throw raiseNode.raise(IndexError, ErrorMessages.INVALID_BUFFER_ACCESS);
380+
}
366381
}
367382
}
368383
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GT__;
4141
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LE__;
4242
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LT__;
43+
import static com.oracle.graal.python.runtime.exception.PythonErrorType.IndexError;
4344
import static com.oracle.graal.python.runtime.exception.PythonErrorType.MemoryError;
4445
import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError;
4546
import static com.oracle.graal.python.runtime.exception.PythonErrorType.SystemError;
@@ -2150,17 +2151,31 @@ public abstract static class CopyBytesFromByteStorage extends PNodeWithContext {
21502151
public abstract void execute(SequenceStorage src, int srcPos, byte[] dest, int destPos, int length);
21512152

21522153
@Specialization
2153-
static void doByteSequenceStorage(ByteSequenceStorage src, int srcPos, byte[] dest, int destPos, int length) {
2154-
PythonUtils.arraycopy(src.getInternalByteArray(), srcPos, dest, destPos, length);
2154+
static void doByteSequenceStorage(ByteSequenceStorage src, int srcPos, byte[] dest, int destPos, int length,
2155+
@Cached PRaiseNode raiseNode) {
2156+
try {
2157+
PythonUtils.arraycopy(src.getInternalByteArray(), srcPos, dest, destPos, length);
2158+
} catch (ArrayIndexOutOfBoundsException e) {
2159+
CompilerDirectives.transferToInterpreterAndInvalidate();
2160+
// This can happen when the array gets resized while being exported
2161+
throw raiseNode.raise(IndexError, ErrorMessages.INVALID_BUFFER_ACCESS);
2162+
}
21552163
}
21562164

21572165
@Specialization(guards = "isByteStorage(src)")
21582166
static void doNativeByte(NativeSequenceStorage src, int srcPos, byte[] dest, int destPos, int length,
2159-
@Cached GetItemScalarNode getItemNode) {
2160-
for (int i = 0; i < length; i++) {
2161-
int elem = getItemNode.executeInt(src, srcPos + i);
2162-
assert elem >= 0 && elem < 256;
2163-
dest[destPos + i] = (byte) elem;
2167+
@Cached GetItemScalarNode getItemNode,
2168+
@Cached PRaiseNode raiseNode) {
2169+
try {
2170+
for (int i = 0; i < length; i++) {
2171+
int elem = getItemNode.executeInt(src, srcPos + i);
2172+
assert elem >= 0 && elem < 256;
2173+
dest[destPos + i] = (byte) elem;
2174+
}
2175+
} catch (PException e) {
2176+
CompilerDirectives.transferToInterpreterAndInvalidate();
2177+
// This can happen when the array gets resized while being exported
2178+
throw raiseNode.raise(IndexError, ErrorMessages.INVALID_BUFFER_ACCESS);
21642179
}
21652180
}
21662181
}
@@ -2172,15 +2187,29 @@ public abstract static class CopyBytesToByteStorage extends PNodeWithContext {
21722187
public abstract void execute(byte[] src, int srcPos, SequenceStorage dest, int destPos, int length);
21732188

21742189
@Specialization
2175-
static void doByteSequenceStorage(byte[] src, int srcPos, ByteSequenceStorage dest, int destPos, int length) {
2176-
PythonUtils.arraycopy(src, srcPos, dest.getInternalByteArray(), destPos, length);
2190+
static void doByteSequenceStorage(byte[] src, int srcPos, ByteSequenceStorage dest, int destPos, int length,
2191+
@Cached PRaiseNode raiseNode) {
2192+
try {
2193+
PythonUtils.arraycopy(src, srcPos, dest.getInternalByteArray(), destPos, length);
2194+
} catch (ArrayIndexOutOfBoundsException e) {
2195+
CompilerDirectives.transferToInterpreterAndInvalidate();
2196+
// This can happen when the array gets resized while being exported
2197+
throw raiseNode.raise(IndexError, ErrorMessages.INVALID_BUFFER_ACCESS);
2198+
}
21772199
}
21782200

21792201
@Specialization(guards = "isByteStorage(dest)")
21802202
static void doNativeByte(byte[] src, int srcPos, NativeSequenceStorage dest, int destPos, int length,
2181-
@Cached SetItemScalarNode setItemNode) {
2182-
for (int i = 0; i < length; i++) {
2183-
setItemNode.execute(dest, destPos + i, src[srcPos + i]);
2203+
@Cached SetItemScalarNode setItemNode,
2204+
@Cached PRaiseNode raiseNode) {
2205+
try {
2206+
for (int i = 0; i < length; i++) {
2207+
setItemNode.execute(dest, destPos + i, src[srcPos + i]);
2208+
}
2209+
} catch (PException e) {
2210+
CompilerDirectives.transferToInterpreterAndInvalidate();
2211+
// This can happen when the array gets resized while being exported
2212+
throw raiseNode.raise(IndexError, ErrorMessages.INVALID_BUFFER_ACCESS);
21842213
}
21852214
}
21862215
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ public abstract class ErrorMessages {
323323
public static final String INVALID_PTR_OBJ = "invalid pointer object: %s";
324324
public static final String INVALID_SYNTAX = "invalid syntax";
325325
public static final String INVALID_USE_OF_W_FORMAT_CHAR = "invalid use of 'w' format character";
326+
public static final String INVALID_BUFFER_ACCESS = "invalid buffer access";
326327
public static final String IS_EMPTY = "%s is empty";
327328
public static final String IS_NOT_A_DICTIONARY = "%s is not a dictionary";
328329
public static final String IS_NOT_IN_RANGE = "%s is not in range";

0 commit comments

Comments
 (0)