Commit 38cf8831 authored by Stefan Behnel's avatar Stefan Behnel

compile time/runtime checks for array slice assignments

parent d48faaeb
......@@ -1830,6 +1830,7 @@ class SliceIndexNode(ExprNode):
if rhs.type.is_array:
# FIXME: we should check both array sizes here
array_length = rhs.type.size
self.generate_slice_guard_code(code, array_length)
else:
# FIXME: fix the array size according to start/stop
array_length = self.base.type.size
......@@ -1852,6 +1853,54 @@ class SliceIndexNode(ExprNode):
self.start_code(),
self.stop_code()))
self.generate_subexpr_disposal_code(code)
def generate_slice_guard_code(self, code, target_size):
if not self.base.type.is_array:
return
slice_size = self.base.type.size
start = stop = None
if self.stop:
stop = self.stop.result()
try:
stop = int(stop)
if stop > 0:
slice_size = stop
else:
slice_size = self.base.type.size + stop
stop = None
except ValueError:
pass
if self.start:
start = self.start.result()
try:
start = int(start)
if start < 0:
start = self.base.type.size + start
slice_size -= start
start = None
except ValueError:
pass
check = None
if slice_size < 0:
if target_size > 0:
error(self.pos, "Assignment to empty slice.")
elif start is None and stop is None:
# we know the exact slice length
if target_size != slice_size:
error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
slice_size, target_size))
elif start is not None:
if stop is None:
stop = slice_size
check = "(%s)-(%s)" % (stop, start)
else: # stop is not None:
check = stop
if check:
code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
target_size, check))
code.putln(code.error_goto(self.pos))
code.putln("}")
def start_code(self):
if self.start:
......
......@@ -8,12 +8,44 @@ __doc__ = u"""
>>> test_literal_list_slice_start_end()
(1, 2, 3, 4, 5)
>>> test_literal_list_slice_start_param(2)
>>> test_literal_list_slice_start_param(4)
(1, 2, 3, 4, 5)
>>> test_literal_list_slice_end_param(4)
>>> test_literal_list_slice_start_param(3)
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 5, got 6
>>> test_literal_list_slice_start_param(5)
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 5, got 4
>>> test_literal_list_slice_end_param(5)
(1, 2, 3, 4, 5)
>>> test_literal_list_slice_end_param(4)
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 5, got 4
>>> test_literal_list_slice_end_param(6)
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 5, got 6
>>> test_literal_list_slice_start_end_param(2,7)
(1, 2, 3, 4, 5)
>>> test_literal_list_slice_start_end_param(3,7)
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 5, got 4
>>> test_literal_list_slice_start_end_param(1,7)
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 5, got 6
>>> test_literal_list_slice_start_end_param(2,6)
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 5, got 4
>>> test_literal_list_slice_start_end_param(2,8)
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 5, got 6
>>> test_literal_list_slice_start_end_param(3,6)
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 5, got 3
>>> test_literal_list_slice_start_end_param(1,8)
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 5, got 7
>>> test_ptr_literal_list_slice_all()
(1, 2, 3, 4, 5)
......@@ -53,7 +85,7 @@ def test_literal_list_slice_start_end():
def test_literal_list_slice_start_param(s):
cdef int a[9] # = [9,8,7,6,5,4,3,2,1]
a[s:] = [1,2,3,4,5]
return (a[2], a[3], a[4], a[5], a[6])
return (a[4], a[5], a[6], a[7], a[8])
# return a[s:]
def test_literal_list_slice_end_param(e):
......
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