Commit f72eb896 authored by Stefan Behnel's avatar Stefan Behnel

add visible warning when negative indices are used in wraparound=False sections

parent 2599587c
......@@ -91,6 +91,7 @@ def find_coercion_error(type_tuple, default, env):
else:
return err
def default_str_type(env):
return {
'bytes': bytes_type,
......@@ -99,6 +100,22 @@ def default_str_type(env):
}.get(env.directives['c_string_type'])
def check_negative_indices(*nodes):
"""
Raise a warning on nodes that are known to have negative numeric values.
Used to find (potential) bugs inside of "wraparound=False" sections.
"""
for node in nodes:
if not isinstance(node.constant_result, (int, float, long)):
continue
if node.constant_result >= 0:
continue
warning(node.pos,
"the result of using negative indices inside of "
"code sections marked as 'wraparound=False' is "
"undefined", level=1)
class ExprNode(Node):
# subexprs [string] Class var holding names of subexpr node attrs
# type PyrexType Type of the result
......@@ -2762,6 +2779,12 @@ class IndexNode(ExprNode):
is_slice = isinstance(self.index, SliceNode)
if not env.directives['wraparound']:
if is_slice:
check_negative_indices(self.index.start, self.index.stop)
else:
check_negative_indices(self.index)
# Potentially overflowing index value.
if not is_slice and isinstance(self.index, IntNode) and Utils.long_literal(self.index.value):
self.index = self.index.coerce_to_pyobject(env)
......@@ -3550,6 +3573,10 @@ class SliceIndexNode(ExprNode):
self.start = self.start.analyse_types(env)
if self.stop:
self.stop = self.stop.analyse_types(env)
if not env.directives['wraparound']:
check_negative_indices(self.start, self.stop)
base_type = self.base.type
if base_type.is_string or base_type.is_cpp_string:
self.type = default_str_type(env)
......
# mode: error
# tag: werror
cimport cython
s = "abc"
l = [1, 2, 3]
def normal_wraparound(int i, bytes B not None, list L not None):
a = s[1:2]
a = s[-2:-1]
a = "abc"[-2:-1]
a = "abc"[-2:i]
a = B[-2:-1]
b = l[1:2]
b = l[-2:-1]
b = [1, 2, 3][-2:-1]
b = [1, 2, 3][-2:i]
b = L[-2:-1]
@cython.wraparound(False)
def no_wraparound(int i, bytes B not None, list L not None):
a = s[1:2]
a = s[-2:-1]
a = "abc"[-2:-1]
a = "abc"[-2:i]
a = B[-2:-1]
b = l[1:2]
b = l[-2:-1]
b = [1, 2, 3][-2:i]
b = L[-2:-1]
_ERRORS = """
25:11: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
25:14: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
27:15: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
28:11: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
28:14: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
31:11: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
31:14: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
32:19: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
33:11: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
33:14: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
"""
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