Skip to content

Commit e659cd1

Browse files
committed
Check for overflows when [re]allocating arrays
1 parent db64f90 commit e659cd1

File tree

6 files changed

+201
-89
lines changed

6 files changed

+201
-89
lines changed

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_array.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
*graalpython.lib-python.3.test.test_array.ByteTest.test_type_error
5757
*graalpython.lib-python.3.test.test_array.ByteTest.test_weakref
5858
*graalpython.lib-python.3.test.test_array.DoubleTest.test_add
59+
*graalpython.lib-python.3.test.test_array.DoubleTest.test_alloc_overflow
5960
*graalpython.lib-python.3.test.test_array.DoubleTest.test_assignment
6061
*graalpython.lib-python.3.test.test_array.DoubleTest.test_buffer_info
6162
*graalpython.lib-python.3.test.test_array.DoubleTest.test_bug_782369
@@ -273,6 +274,7 @@
273274
*graalpython.lib-python.3.test.test_array.LongLongTest.test_len
274275
*graalpython.lib-python.3.test.test_array.LongLongTest.test_mul
275276
*graalpython.lib-python.3.test.test_array.LongLongTest.test_obsolete_write_lock
277+
*graalpython.lib-python.3.test.test_array.LongLongTest.test_overflow
276278
*graalpython.lib-python.3.test.test_array.LongLongTest.test_pickle
277279
*graalpython.lib-python.3.test.test_array.LongLongTest.test_pickle_for_empty_array
278280
*graalpython.lib-python.3.test.test_array.LongLongTest.test_pop
@@ -329,6 +331,7 @@
329331
*graalpython.lib-python.3.test.test_array.LongTest.test_len
330332
*graalpython.lib-python.3.test.test_array.LongTest.test_mul
331333
*graalpython.lib-python.3.test.test_array.LongTest.test_obsolete_write_lock
334+
*graalpython.lib-python.3.test.test_array.LongTest.test_overflow
332335
*graalpython.lib-python.3.test.test_array.LongTest.test_pickle
333336
*graalpython.lib-python.3.test.test_array.LongTest.test_pickle_for_empty_array
334337
*graalpython.lib-python.3.test.test_array.LongTest.test_pop

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626
package com.oracle.graal.python.builtins.modules;
2727

28+
import static com.oracle.graal.python.runtime.exception.PythonErrorType.MemoryError;
2829
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
2930
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
3031

@@ -60,7 +61,10 @@
6061
import com.oracle.graal.python.runtime.exception.PException;
6162
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
6263
import com.oracle.graal.python.util.BufferFormat;
64+
import com.oracle.graal.python.util.OverflowException;
65+
import com.oracle.graal.python.util.PythonUtils;
6366
import com.oracle.truffle.api.CompilerDirectives;
67+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
6468
import com.oracle.truffle.api.dsl.Cached;
6569
import com.oracle.truffle.api.dsl.Fallback;
6670
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
@@ -70,6 +74,7 @@
7074
import com.oracle.truffle.api.frame.VirtualFrame;
7175
import com.oracle.truffle.api.library.CachedLibrary;
7276
import com.oracle.truffle.api.nodes.Node;
77+
import com.oracle.truffle.api.profiles.ValueProfile;
7378

7479
@CoreFunctions(defineModule = "array")
7580
public final class ArrayModuleBuiltins extends PythonBuiltins {
@@ -142,6 +147,7 @@ public final Object varArgExecute(VirtualFrame frame, @SuppressWarnings("unused"
142147
abstract static class ArrayNodeInternal extends Node {
143148
@Child private PRaiseNode raiseNode;
144149
@Child private PythonObjectFactory factory;
150+
@CompilationFinal private ValueProfile formatProfile = ValueProfile.createIdentityProfile();
145151

146152
public abstract PArray execute(VirtualFrame frame, Object cls, String typeCode, Object initializer);
147153

@@ -155,7 +161,13 @@ PArray array(Object cls, String typeCode, @SuppressWarnings("unused") PNone init
155161
PArray arrayWithRangeInitializer(Object cls, String typeCode, PIntRange range,
156162
@Cached ArrayNodes.PutValueNode putValueNode) {
157163
BufferFormat format = getFormatChecked(typeCode);
158-
PArray array = getFactory().createArray(cls, typeCode, format, range.getIntLength());
164+
PArray array;
165+
try {
166+
array = getFactory().createArray(cls, typeCode, format, range.getIntLength());
167+
} catch (OverflowException e) {
168+
CompilerDirectives.transferToInterpreterAndInvalidate();
169+
throw raise(MemoryError);
170+
}
159171

160172
int start = range.getIntStart();
161173
int stop = range.getIntStop();
@@ -178,7 +190,7 @@ PArray arrayWithBytesInitializer(VirtualFrame frame, Object cls, String typeCode
178190

179191
// TODO impl for PSequence and PArray or use lenght_hint
180192

181-
@Specialization(limit = "3")
193+
@Specialization(guards = "!isBytes(initializer)", limit = "3")
182194
PArray arrayIteratorInitializer(VirtualFrame frame, Object cls, String typeCode, Object initializer,
183195
@CachedLibrary("initializer") PythonObjectLibrary lib,
184196
@Cached ArrayNodes.PutValueNode putValueNode,
@@ -189,7 +201,7 @@ PArray arrayIteratorInitializer(VirtualFrame frame, Object cls, String typeCode,
189201
BufferFormat format = getFormatChecked(typeCode);
190202
PArray array = getFactory().createArray(cls, typeCode, format);
191203

192-
int lenght = 0;
204+
int length = 0;
193205
while (true) {
194206
Object nextValue;
195207
try {
@@ -198,11 +210,17 @@ PArray arrayIteratorInitializer(VirtualFrame frame, Object cls, String typeCode,
198210
e.expectStopIteration(errorProfile);
199211
break;
200212
}
201-
array.ensureCapacity(++lenght);
202-
putValueNode.execute(frame, array, lenght - 1, nextValue);
213+
try {
214+
length = PythonUtils.addExact(length, 1);
215+
array.ensureCapacity(length);
216+
} catch (OverflowException e) {
217+
CompilerDirectives.transferToInterpreterAndInvalidate();
218+
throw raise(MemoryError);
219+
}
220+
putValueNode.execute(frame, array, length - 1, nextValue);
203221
}
204222

205-
array.setLenght(lenght);
223+
array.setLenght(length);
206224
return array;
207225
}
208226

@@ -214,7 +232,7 @@ private BufferFormat getFormatChecked(String typeCode) {
214232
if (format == null) {
215233
throw raise(ValueError, "bad typecode (must be b, B, u, h, H, i, I, l, L, q, Q, f or d)");
216234
}
217-
return format;
235+
return formatProfile.profile(format);
218236
}
219237

220238
private PException raise(PythonBuiltinClassType type, String message, Object... args) {
@@ -225,6 +243,14 @@ private PException raise(PythonBuiltinClassType type, String message, Object...
225243
throw raiseNode.raise(type, message, args);
226244
}
227245

246+
private PException raise(PythonBuiltinClassType type) {
247+
if (raiseNode == null) {
248+
CompilerDirectives.transferToInterpreterAndInvalidate();
249+
raiseNode = insert(PRaiseNode.create());
250+
}
251+
throw raiseNode.raise(type);
252+
}
253+
228254
private PythonObjectFactory getFactory() {
229255
if (factory == null) {
230256
CompilerDirectives.transferToInterpreterAndInvalidate();

0 commit comments

Comments
 (0)