Commit 1657608e authored by Robert Bradshaw's avatar Robert Bradshaw

Implement overflow check for abs(int).

parent f05f6164
...@@ -5510,6 +5510,8 @@ class SimpleCallNode(CallNode): ...@@ -5510,6 +5510,8 @@ class SimpleCallNode(CallNode):
if func_type.exception_value is None: if func_type.exception_value is None:
env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp"))
self.overflowcheck = env.directives['overflowcheck']
def calculate_result_code(self): def calculate_result_code(self):
return self.c_call_code() return self.c_call_code()
...@@ -5620,7 +5622,12 @@ class SimpleCallNode(CallNode): ...@@ -5620,7 +5622,12 @@ class SimpleCallNode(CallNode):
translate_cpp_exception(code, self.pos, '%s%s;' % (lhs, rhs), translate_cpp_exception(code, self.pos, '%s%s;' % (lhs, rhs),
func_type.exception_value, self.nogil) func_type.exception_value, self.nogil)
else: else:
if exc_checks: if (self.overflowcheck
and self.type.is_int
and self.type.signed
and self.function.result() in ('abs', 'labs', '__Pyx_abs_longlong')):
goto_error = 'if (%s < 0) { PyErr_SetString(PyExc_OverflowError, "value too large"); %s; }' % (self.result(), code.error_goto(self.pos))
elif exc_checks:
goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos) goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
else: else:
goto_error = "" goto_error = ""
......
...@@ -41,6 +41,7 @@ def sub_abs(int a): ...@@ -41,6 +41,7 @@ def sub_abs(int a):
""" """
return -abs(a), 100 - abs(a) return -abs(a), 100 - abs(a)
@cython.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
"//ReturnStatNode//NameNode[@entry.cname = 'abs']") "//ReturnStatNode//NameNode[@entry.cname = 'abs']")
def int_abs(int a): def int_abs(int a):
...@@ -49,12 +50,10 @@ def int_abs(int a): ...@@ -49,12 +50,10 @@ def int_abs(int a):
True True
>>> int_abs(-5.1) == 5 >>> int_abs(-5.1) == 5
True True
""" >>> int_abs(-max_int-1) #doctest: +ELLIPSIS
# >>> int_abs(-max_int-1) > 0 Traceback (most recent call last):
# True ...
# >>> int_abs(-max_int-1) == abs(-max_int-1) or (max_int, int_abs(-max_int-1), abs(-max_int-1)) OverflowError: ...
# True
"""
>>> int_abs(max_int) == abs(max_int) or (max_int, int_abs(max_int), abs(max_int)) >>> int_abs(max_int) == abs(max_int) or (max_int, int_abs(max_int), abs(max_int))
True True
""" """
...@@ -70,6 +69,7 @@ def uint_abs(unsigned int a): ...@@ -70,6 +69,7 @@ def uint_abs(unsigned int a):
""" """
return abs(a) return abs(a)
@cython.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
"//ReturnStatNode//NameNode[@entry.cname = 'labs']") "//ReturnStatNode//NameNode[@entry.cname = 'labs']")
def long_abs(long a): def long_abs(long a):
...@@ -78,12 +78,10 @@ def long_abs(long a): ...@@ -78,12 +78,10 @@ def long_abs(long a):
True True
>>> long_abs(-5.1) == 5 >>> long_abs(-5.1) == 5
True True
""" >>> long_abs(-max_long-1) #doctest: +ELLIPSIS
# >>> long_abs(-max_long-1) > 0 Traceback (most recent call last):
# True ...
# >>> long_abs(-max_long-1) == abs(-max_long-1) or (max_long, long_abs(-max_long-1), abs(-max_long-1)) OverflowError: ...
# True
"""
>>> long_abs(max_long) == abs(max_long) or (max_long, long_abs(max_long), abs(max_long)) >>> long_abs(max_long) == abs(max_long) or (max_long, long_abs(max_long), abs(max_long))
True True
""" """
...@@ -101,18 +99,17 @@ def ulong_abs(unsigned long a): ...@@ -101,18 +99,17 @@ def ulong_abs(unsigned long a):
""" """
return abs(a) return abs(a)
@cython.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
"//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_longlong']") "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_longlong']")
def long_long_abs(long long a): def long_long_abs(long long a):
""" """
>>> long_long_abs(-(2**33)) == 2**33 >>> long_long_abs(-(2**33)) == 2**33
True True
""" >>> long_long_abs(-max_long_long-1) #doctest: +ELLIPSIS
# >>> long_long_abs(-max_long_long-1) > 0 Traceback (most recent call last):
# True ...
# >>> long_long_abs(-max_long_long-1) == abs(-max_long_long-1) or (max_long_long, long_long_abs(-max_long_long-1), abs(-max_long_long-1)) OverflowError: ...
# True
"""
>>> long_long_abs(max_long_long) == abs(max_long_long) or (max_long_long, long_long_abs(max_long_long), abs(max_long_long)) >>> long_long_abs(max_long_long) == abs(max_long_long) or (max_long_long, long_long_abs(max_long_long), abs(max_long_long))
True True
""" """
......
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