Skip to content

Commit ade1b26

Browse files
committed
Add buffer exports checking to array and bytearray
1 parent 7f619a3 commit ade1b26

File tree

8 files changed

+175
-75
lines changed

8 files changed

+175
-75
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
*graalpython.lib-python.3.test.test_array.ByteTest.test_add
22
*graalpython.lib-python.3.test.test_array.ByteTest.test_assignment
3+
*graalpython.lib-python.3.test.test_array.ByteTest.test_buffer
34
*graalpython.lib-python.3.test.test_array.ByteTest.test_buffer_info
45
*graalpython.lib-python.3.test.test_array.ByteTest.test_bug_782369
56
*graalpython.lib-python.3.test.test_array.ByteTest.test_byteswap
@@ -58,6 +59,7 @@
5859
*graalpython.lib-python.3.test.test_array.DoubleTest.test_add
5960
*graalpython.lib-python.3.test.test_array.DoubleTest.test_alloc_overflow
6061
*graalpython.lib-python.3.test.test_array.DoubleTest.test_assignment
62+
*graalpython.lib-python.3.test.test_array.DoubleTest.test_buffer
6163
*graalpython.lib-python.3.test.test_array.DoubleTest.test_buffer_info
6264
*graalpython.lib-python.3.test.test_array.DoubleTest.test_bug_782369
6365
*graalpython.lib-python.3.test.test_array.DoubleTest.test_byteswap
@@ -114,6 +116,7 @@
114116
*graalpython.lib-python.3.test.test_array.DoubleTest.test_weakref
115117
*graalpython.lib-python.3.test.test_array.FloatTest.test_add
116118
*graalpython.lib-python.3.test.test_array.FloatTest.test_assignment
119+
*graalpython.lib-python.3.test.test_array.FloatTest.test_buffer
117120
*graalpython.lib-python.3.test.test_array.FloatTest.test_buffer_info
118121
*graalpython.lib-python.3.test.test_array.FloatTest.test_bug_782369
119122
*graalpython.lib-python.3.test.test_array.FloatTest.test_byteswap
@@ -170,6 +173,7 @@
170173
*graalpython.lib-python.3.test.test_array.FloatTest.test_weakref
171174
*graalpython.lib-python.3.test.test_array.IntTest.test_add
172175
*graalpython.lib-python.3.test.test_array.IntTest.test_assignment
176+
*graalpython.lib-python.3.test.test_array.IntTest.test_buffer
173177
*graalpython.lib-python.3.test.test_array.IntTest.test_buffer_info
174178
*graalpython.lib-python.3.test.test_array.IntTest.test_bug_782369
175179
*graalpython.lib-python.3.test.test_array.IntTest.test_byteswap
@@ -241,6 +245,7 @@
241245
*graalpython.lib-python.3.test.test_array.LargeArrayTest.test_tolist
242246
*graalpython.lib-python.3.test.test_array.LongLongTest.test_add
243247
*graalpython.lib-python.3.test.test_array.LongLongTest.test_assignment
248+
*graalpython.lib-python.3.test.test_array.LongLongTest.test_buffer
244249
*graalpython.lib-python.3.test.test_array.LongLongTest.test_buffer_info
245250
*graalpython.lib-python.3.test.test_array.LongLongTest.test_bug_782369
246251
*graalpython.lib-python.3.test.test_array.LongLongTest.test_byteswap
@@ -298,6 +303,7 @@
298303
*graalpython.lib-python.3.test.test_array.LongLongTest.test_weakref
299304
*graalpython.lib-python.3.test.test_array.LongTest.test_add
300305
*graalpython.lib-python.3.test.test_array.LongTest.test_assignment
306+
*graalpython.lib-python.3.test.test_array.LongTest.test_buffer
301307
*graalpython.lib-python.3.test.test_array.LongTest.test_buffer_info
302308
*graalpython.lib-python.3.test.test_array.LongTest.test_bug_782369
303309
*graalpython.lib-python.3.test.test_array.LongTest.test_byteswap
@@ -357,6 +363,7 @@
357363
*graalpython.lib-python.3.test.test_array.MiscTest.test_empty
358364
*graalpython.lib-python.3.test.test_array.ShortTest.test_add
359365
*graalpython.lib-python.3.test.test_array.ShortTest.test_assignment
366+
*graalpython.lib-python.3.test.test_array.ShortTest.test_buffer
360367
*graalpython.lib-python.3.test.test_array.ShortTest.test_buffer_info
361368
*graalpython.lib-python.3.test.test_array.ShortTest.test_bug_782369
362369
*graalpython.lib-python.3.test.test_array.ShortTest.test_byteswap
@@ -413,6 +420,7 @@
413420
*graalpython.lib-python.3.test.test_array.ShortTest.test_type_error
414421
*graalpython.lib-python.3.test.test_array.ShortTest.test_weakref
415422
*graalpython.lib-python.3.test.test_array.UnicodeTest.test_add
423+
*graalpython.lib-python.3.test.test_array.UnicodeTest.test_buffer
416424
*graalpython.lib-python.3.test.test_array.UnicodeTest.test_buffer_info
417425
*graalpython.lib-python.3.test.test_array.UnicodeTest.test_bug_782369
418426
*graalpython.lib-python.3.test.test_array.UnicodeTest.test_byteswap
@@ -466,6 +474,7 @@
466474
*graalpython.lib-python.3.test.test_array.UnicodeTest.test_weakref
467475
*graalpython.lib-python.3.test.test_array.UnsignedByteTest.test_add
468476
*graalpython.lib-python.3.test.test_array.UnsignedByteTest.test_assignment
477+
*graalpython.lib-python.3.test.test_array.UnsignedByteTest.test_buffer
469478
*graalpython.lib-python.3.test.test_array.UnsignedByteTest.test_buffer_info
470479
*graalpython.lib-python.3.test.test_array.UnsignedByteTest.test_bug_782369
471480
*graalpython.lib-python.3.test.test_array.UnsignedByteTest.test_bytes_extend
@@ -524,6 +533,7 @@
524533
*graalpython.lib-python.3.test.test_array.UnsignedByteTest.test_weakref
525534
*graalpython.lib-python.3.test.test_array.UnsignedIntTest.test_add
526535
*graalpython.lib-python.3.test.test_array.UnsignedIntTest.test_assignment
536+
*graalpython.lib-python.3.test.test_array.UnsignedIntTest.test_buffer
527537
*graalpython.lib-python.3.test.test_array.UnsignedIntTest.test_buffer_info
528538
*graalpython.lib-python.3.test.test_array.UnsignedIntTest.test_bug_782369
529539
*graalpython.lib-python.3.test.test_array.UnsignedIntTest.test_bytes_extend
@@ -582,6 +592,7 @@
582592
*graalpython.lib-python.3.test.test_array.UnsignedIntTest.test_weakref
583593
*graalpython.lib-python.3.test.test_array.UnsignedLongLongTest.test_add
584594
*graalpython.lib-python.3.test.test_array.UnsignedLongLongTest.test_assignment
595+
*graalpython.lib-python.3.test.test_array.UnsignedLongLongTest.test_buffer
585596
*graalpython.lib-python.3.test.test_array.UnsignedLongLongTest.test_buffer_info
586597
*graalpython.lib-python.3.test.test_array.UnsignedLongLongTest.test_bug_782369
587598
*graalpython.lib-python.3.test.test_array.UnsignedLongLongTest.test_bytes_extend
@@ -640,6 +651,7 @@
640651
*graalpython.lib-python.3.test.test_array.UnsignedLongLongTest.test_weakref
641652
*graalpython.lib-python.3.test.test_array.UnsignedLongTest.test_add
642653
*graalpython.lib-python.3.test.test_array.UnsignedLongTest.test_assignment
654+
*graalpython.lib-python.3.test.test_array.UnsignedLongTest.test_buffer
643655
*graalpython.lib-python.3.test.test_array.UnsignedLongTest.test_buffer_info
644656
*graalpython.lib-python.3.test.test_array.UnsignedLongTest.test_bug_782369
645657
*graalpython.lib-python.3.test.test_array.UnsignedLongTest.test_bytes_extend
@@ -698,6 +710,7 @@
698710
*graalpython.lib-python.3.test.test_array.UnsignedLongTest.test_weakref
699711
*graalpython.lib-python.3.test.test_array.UnsignedShortTest.test_add
700712
*graalpython.lib-python.3.test.test_array.UnsignedShortTest.test_assignment
713+
*graalpython.lib-python.3.test.test_array.UnsignedShortTest.test_buffer
701714
*graalpython.lib-python.3.test.test_array.UnsignedShortTest.test_buffer_info
702715
*graalpython.lib-python.3.test.test_array.UnsignedShortTest.test_bug_782369
703716
*graalpython.lib-python.3.test.test_array.UnsignedShortTest.test_bytes_extend

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
*graalpython.lib-python.3.test.test_bytes.ByteArrayTest.test_repeat_1char
127127
*graalpython.lib-python.3.test.test_bytes.ByteArrayTest.test_replace
128128
*graalpython.lib-python.3.test.test_bytes.ByteArrayTest.test_replace_int_error
129+
*graalpython.lib-python.3.test.test_bytes.ByteArrayTest.test_resize_forbidden
129130
*graalpython.lib-python.3.test.test_bytes.ByteArrayTest.test_reverse
130131
*graalpython.lib-python.3.test.test_bytes.ByteArrayTest.test_reversed
131132
*graalpython.lib-python.3.test.test_bytes.ByteArrayTest.test_rfind

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3404,6 +3404,7 @@ PMemoryView fromByteArray(@SuppressWarnings("unused") Object cls, PByteArray obj
34043404
@Shared("getQueue") @Cached MemoryViewNodes.GetBufferReferences getQueue,
34053405
@Cached SequenceNodes.GetSequenceStorageNode getSequenceStorageNode,
34063406
@Cached SequenceStorageNodes.LenNode lenNode) {
3407+
object.incrementExports();
34073408
SequenceStorage storage = getSequenceStorageNode.execute(object);
34083409
return fromManaged(object, 1, lenNode.execute(storage), false, "B", true, getQueue.execute());
34093410
}
@@ -3412,6 +3413,7 @@ PMemoryView fromByteArray(@SuppressWarnings("unused") Object cls, PByteArray obj
34123413
PMemoryView fromArray(@SuppressWarnings("unused") Object cls, PArray object,
34133414
@Shared("getQueue") @Cached MemoryViewNodes.GetBufferReferences getQueue) {
34143415
int itemsize = object.getFormat().bytesize;
3416+
object.incrementExports();
34153417
return fromManaged(object, itemsize, object.getLength(), false, object.getFormatStr(), true, getQueue.execute());
34163418
}
34173419

@@ -3451,7 +3453,6 @@ private PMemoryView fromManaged(Object object, int itemsize, int length, boolean
34513453
MemoryViewNodes.BufferReferences refQueue) {
34523454
ManagedBuffer managedBuffer = null;
34533455
if (needsRelease) {
3454-
// TODO We should lock the underlying storage for resizing
34553456
managedBuffer = ManagedBuffer.createForManaged(object);
34563457
}
34573458
return factory().createMemoryView(refQueue, managedBuffer, object, length * itemsize, readonly, itemsize, format, 1,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/array/ArrayBuiltins.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ abstract static class IMulNode extends PythonBinaryClinicBuiltinNode {
201201
Object concat(PArray self, int value) {
202202
try {
203203
int newLength = Math.max(PythonUtils.multiplyExact(self.getLength(), value), 0);
204+
if (newLength != self.getLength()) {
205+
self.checkCanResize(this);
206+
}
204207
int itemsize = self.getFormat().bytesize;
205208
int segmentLength = self.getLength() * itemsize;
206209
self.resize(newLength);
@@ -533,6 +536,7 @@ Object setitem(PArray self, PSlice slice, PArray other,
533536
}
534537
if (simpleStepProfile.profile(step == 1)) {
535538
if (differentLengthProfile.profile(sliceLength != needed)) {
539+
self.checkCanResize(this);
536540
if (growProfile.profile(sliceLength < needed)) {
537541
if (stop < start) {
538542
stop = start;
@@ -579,19 +583,21 @@ abstract static class DelItemNode extends PythonBinaryBuiltinNode {
579583
public abstract Object executeSlice(PArray self, PSlice slice);
580584

581585
@Specialization(guards = "!isPSlice(idx)", limit = "3")
582-
static Object delitem(PArray self, Object idx,
586+
Object delitem(PArray self, Object idx,
583587
@CachedLibrary("idx") PythonObjectLibrary lib,
584588
@Cached("forArrayAssign()") NormalizeIndexNode normalizeIndexNode) {
589+
self.checkCanResize(this);
585590
int index = normalizeIndexNode.execute(lib.asIndex(idx), self.getLength());
586591
self.delSlice(index, 1);
587592
return PNone.NONE;
588593
}
589594

590595
@Specialization
591-
static Object delitem(PArray self, PSlice slice,
596+
Object delitem(PArray self, PSlice slice,
592597
@Cached ConditionProfile simpleStepProfile,
593598
@Cached SliceLiteralNode.SliceUnpack sliceUnpack,
594599
@Cached SliceLiteralNode.AdjustIndices adjustIndices) {
600+
self.checkCanResize(this);
595601
int length = self.getLength();
596602
PSlice.SliceInfo sliceInfo = adjustIndices.execute(length, sliceUnpack.execute(slice));
597603
int start = sliceInfo.start;
@@ -713,6 +719,7 @@ Object append(VirtualFrame frame, PArray self, Object value,
713719
try {
714720
int index = self.getLength();
715721
int newLength = PythonUtils.addExact(index, 1);
722+
self.checkCanResize(this);
716723
self.resize(newLength);
717724
putValueNode.execute(frame, self, index, value);
718725
return PNone.NONE;
@@ -730,6 +737,9 @@ abstract static class ExtendNode extends PythonBinaryBuiltinNode {
730737
Object extend(PArray self, PArray value) {
731738
try {
732739
int newLength = PythonUtils.addExact(self.getLength(), value.getLength());
740+
if (newLength != self.getLength()) {
741+
self.checkCanResize(this);
742+
}
733743
int itemsize = self.getFormat().bytesize;
734744
self.resizeStorage(newLength);
735745
PythonUtils.arraycopy(value.getBuffer(), 0, self.getBuffer(), self.getLength() * itemsize, value.getLength() * itemsize);
@@ -750,7 +760,11 @@ Object extend(VirtualFrame frame, PArray self, PSequence value,
750760
SequenceStorage storage = getSequenceStorageNode.execute(value);
751761
int storageLength = lenNode.execute(storage);
752762
try {
753-
self.resizeStorage(PythonUtils.addExact(self.getLength(), storageLength));
763+
int newLength = PythonUtils.addExact(self.getLength(), storageLength);
764+
if (newLength != self.getLength()) {
765+
self.checkCanResize(this);
766+
}
767+
self.resizeStorage(newLength);
754768
} catch (OverflowException e) {
755769
CompilerDirectives.transferToInterpreterAndInvalidate();
756770
throw raise(MemoryError);
@@ -786,6 +800,7 @@ Object extend(VirtualFrame frame, PArray self, Object value,
786800
// in CPython
787801
try {
788802
length = PythonUtils.addExact(length, 1);
803+
self.checkCanResize(this);
789804
self.resizeStorage(length);
790805
} catch (OverflowException e) {
791806
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -825,6 +840,7 @@ Object insert(VirtualFrame frame, PArray self, int inputIndex, Object value,
825840
// Need to check the validity of the value before moving the memory around to ensure the
826841
// operation can fail atomically
827842
checkValueNode.execute(frame, self, value);
843+
self.checkCanResize(this);
828844
try {
829845
self.shift(index, 1);
830846
} catch (OverflowException e) {
@@ -851,6 +867,7 @@ Object remove(VirtualFrame frame, PArray self, Object value,
851867
for (int i = 0; i < self.getLength(); i++) {
852868
Object item = getValueNode.execute(self, i);
853869
if (lib.equalsWithFrame(item, value, lib, frame)) {
870+
self.checkCanResize(this);
854871
self.delSlice(i, 1);
855872
return PNone.NONE;
856873
}
@@ -872,6 +889,7 @@ Object pop(PArray self, int inputIndex,
872889
}
873890
int index = normalizeIndexNode.execute(inputIndex, self.getLength());
874891
Object value = getValueNode.execute(self, index);
892+
self.checkCanResize(this);
875893
self.delSlice(index, 1);
876894
return value;
877895
}
@@ -898,6 +916,7 @@ Object frombytes(PArray self, Object buffer,
898916
}
899917
int newLength = PythonUtils.addExact(oldSize, bufferLength / itemsize);
900918
byte[] bufferBytes = lib.getBufferBytes(buffer);
919+
self.checkCanResize(this);
901920
self.resize(newLength);
902921
PythonUtils.arraycopy(bufferBytes, 0, self.getBuffer(), oldSize * itemsize, bufferLength);
903922
} catch (UnsupportedMessageException e) {
@@ -965,6 +984,7 @@ Object fromlist(VirtualFrame frame, PArray self, PList list,
965984
SequenceStorage storage = getSequenceStorageNode.execute(list);
966985
int length = lenNode.execute(storage);
967986
int newLength = PythonUtils.addExact(self.getLength(), length);
987+
self.checkCanResize(this);
968988
self.resizeStorage(newLength);
969989
for (int i = 0; i < length; i++) {
970990
putValueNode.execute(frame, self, self.getLength() + i, getItemScalarNode.execute(storage, i));
@@ -1017,6 +1037,7 @@ Object fromunicode(VirtualFrame frame, PArray self, String str,
10171037
try {
10181038
int length = PString.codePointCount(str, 0, str.length());
10191039
int newLength = PythonUtils.addExact(self.getLength(), length);
1040+
self.checkCanResize(this);
10201041
self.resizeStorage(newLength);
10211042
for (int i = 0, index = 0; i < length; index++) {
10221043
int cpCount = PString.charCount(PString.codePointAt(str, i));

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/array/PArray.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@
2525
*/
2626
package com.oracle.graal.python.builtins.objects.array;
2727

28+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.BufferError;
29+
2830
import java.nio.ByteOrder;
2931
import java.util.Arrays;
3032

3133
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
3234
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
35+
import com.oracle.graal.python.nodes.ErrorMessages;
36+
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
3337
import com.oracle.graal.python.util.BufferFormat;
3438
import com.oracle.graal.python.util.OverflowException;
3539
import com.oracle.graal.python.util.PythonUtils;
@@ -46,6 +50,7 @@ public final class PArray extends PythonBuiltinObject {
4650
private String formatStr;
4751
private int length;
4852
private byte[] buffer;
53+
private volatile int exports;
4954

5055
public PArray(Object clazz, Shape instanceShape, String formatStr, BufferFormat format) {
5156
super(clazz, instanceShape);
@@ -84,6 +89,28 @@ public void setLength(int length) {
8489
this.length = length;
8590
}
8691

92+
public int getExports() {
93+
return exports;
94+
}
95+
96+
public void setExports(int exports) {
97+
this.exports = exports;
98+
}
99+
100+
public synchronized void incrementExports() {
101+
exports++;
102+
}
103+
104+
public synchronized void decrementExports() {
105+
exports--;
106+
}
107+
108+
public void checkCanResize(PythonBuiltinBaseNode node) {
109+
if (exports != 0) {
110+
throw node.raise(BufferError, ErrorMessages.EXPORTS_CANNOT_RESIZE);
111+
}
112+
}
113+
87114
private int computeNewSize(int newLength, int itemsize) throws OverflowException {
88115
int newSize = computeNewSizeNoOverflowCheck(newLength, itemsize);
89116
if (newSize / itemsize < newLength) {

0 commit comments

Comments
 (0)