Commit fffc5ba3 authored by Stefan Behnel's avatar Stefan Behnel

use at least ssize_t temp variables for buffer index calculations even if...

use at least ssize_t temp variables for buffer index calculations even if users use smaller integer types as we might be doing wrap-around calculations that depend on the potentially larger buffer shape
parent 1ed00742
......@@ -3780,10 +3780,16 @@ class IndexNode(ExprNode):
return buffer_entry
def buffer_lookup_code(self, code):
"ndarray[1, 2, 3] and memslice[1, 2, 3]"
# Assign indices to temps
index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False)
for i in self.indices]
"""
ndarray[1, 2, 3] and memslice[1, 2, 3]
"""
# Assign indices to temps of at least (s)size_t to allow further index calculations.
index_temps = [
code.funcstate.allocate_temp(
PyrexTypes.widest_numeric_type(
ivar.type, PyrexTypes.c_ssize_t_type if ivar.type.signed else PyrexTypes.c_size_t_type),
manage_ref=False)
for ivar in self.indices]
for temp, index in zip(index_temps, self.indices):
code.putln("%s = %s;" % (temp, index.result()))
......@@ -3798,7 +3804,7 @@ class IndexNode(ExprNode):
return buffer_entry, Buffer.put_buffer_lookup_code(
entry=buffer_entry,
index_signeds=[i.type.signed for i in self.indices],
index_signeds=[ivar.type.signed for ivar in self.indices],
index_cnames=index_temps,
directives=code.globalstate.directives,
pos=self.pos, code=code,
......
......@@ -425,6 +425,166 @@ def set_int_2d(int[:, :] buf, int i, int j, int value):
"""
buf[i, j] = value
def _read_int2d(int[:, :] buf, int i, int j):
return buf[i, j]
@testcase
def schar_index_vars(int[:, :] buf, signed char i, signed char j, int value):
"""
>>> C = IntMockBuffer("C", range(300*300), (300, 300)) # > sizeof(char)
>>> schar_index_vars(C, 1, 1, 5)
acquired C
reading
writing
validated
released C
301
>>> _read_int2d(C, 1, 1) # validate with int indices
acquired C
released C
5
>>> schar_index_vars(C, -1, 1, 6)
acquired C
reading
writing
validated
released C
89701
>>> _read_int2d(C, -1, 1) # validate with int indices
acquired C
released C
6
>>> schar_index_vars(C, -1, -2, 7)
acquired C
reading
writing
validated
released C
89998
>>> _read_int2d(C, -1, -2) # validate with int indices
acquired C
released C
7
>>> schar_index_vars(C, -2, -3, 8)
acquired C
reading
writing
validated
released C
89697
>>> _read_int2d(C, -2, -3) # validate with int indices
acquired C
released C
8
>>> C = IntMockBuffer("C", range(6), (2, 3))
>>> schar_index_vars(C, 5, 1, 10)
Traceback (most recent call last):
IndexError: Out of bounds on buffer access (axis 0)
>>> schar_index_vars(C, 1, 5, 10)
Traceback (most recent call last):
IndexError: Out of bounds on buffer access (axis 1)
>>> schar_index_vars(C, -2, 1, 10)
acquired C
reading
writing
validated
released C
1
>>> schar_index_vars(C, -3, 1, 10)
Traceback (most recent call last):
IndexError: Out of bounds on buffer access (axis 0)
>>> schar_index_vars(C, 1, -3, 10)
acquired C
reading
writing
validated
released C
3
>>> schar_index_vars(C, 1, -4, 10)
Traceback (most recent call last):
IndexError: Out of bounds on buffer access (axis 1)
"""
print("reading")
old_value = buf[i, j]
print("writing")
buf[i, j] = value
if buf[i, j] == value:
print("validated")
return old_value
@testcase
def uchar_index_vars(int[:, :] buf, unsigned char i, unsigned char j, int value):
"""
>>> C = IntMockBuffer("C", range(300*300), (300, 300)) # > sizeof(char)
>>> uchar_index_vars(C, 1, 1, 5)
acquired C
reading
writing
validated
released C
301
>>> _read_int2d(C, 1, 1) # validate with int indices
acquired C
released C
5
>>> C = IntMockBuffer("C", range(6), (2, 3))
>>> uchar_index_vars(C, 5, 1, 10)
Traceback (most recent call last):
IndexError: Out of bounds on buffer access (axis 0)
>>> uchar_index_vars(C, 1, 5, 10)
Traceback (most recent call last):
IndexError: Out of bounds on buffer access (axis 1)
"""
print("reading")
old_value = buf[i, j]
print("writing")
buf[i, j] = value
if buf[i, j] == value:
print("validated")
return old_value
@testcase
def char_index_vars(int[:, :] buf, char i, char j, int value):
"""
>>> C = IntMockBuffer("C", range(300*300), (300, 300)) # > sizeof(char)
>>> char_index_vars(C, 1, 1, 5)
acquired C
reading
writing
validated
released C
301
>>> _read_int2d(C, 1, 1) # validate with int indices
acquired C
released C
5
>>> C = IntMockBuffer("C", range(6), (2, 3))
>>> char_index_vars(C, 5, 1, 10)
Traceback (most recent call last):
IndexError: Out of bounds on buffer access (axis 0)
>>> char_index_vars(C, 1, 5, 10)
Traceback (most recent call last):
IndexError: Out of bounds on buffer access (axis 1)
"""
print("reading")
old_value = buf[i, j]
print("writing")
buf[i, j] = value
if buf[i, j] == value:
print("validated")
return old_value
@testcase
def list_comprehension(int[:] buf, len):
"""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment