From 1d47a9ef7dcd6296daff8a27903f9a95131fb603 Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Wed, 15 Apr 2009 00:27:57 -0700 Subject: [PATCH] Require GIL for pythonic division, check for division overflow --- Cython/Compiler/ExprNodes.py | 18 ++++++++++++++++++ tests/run/cdivision_CEP_516.pyx | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 9d274b94..732d5be8 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -4247,6 +4247,8 @@ class DivNode(NumBinopNode): # Need to check ahead of time to warn or raise zero division error self.operand1 = self.operand1.coerce_to_simple(env) self.operand2 = self.operand2.coerce_to_simple(env) + if env.nogil: + error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)") def zero_division_message(self): if self.type.is_int: @@ -4272,6 +4274,15 @@ class DivNode(NumBinopNode): code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message()) code.putln(code.error_goto(self.pos)) code.putln("}") + if self.type.is_int and self.type.signed and self.operator != '%': + code.globalstate.use_utility_code(division_overflow_test_code) + code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % ( + self.type.declaration_code(''), + self.operand2.result(), + self.operand1.result())) + code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");') + code.putln(code.error_goto(self.pos)) + code.putln("}") if code.globalstate.directives['cdivision_warnings']: code.globalstate.use_utility_code(cdivision_warning_utility_code) code.putln("if ((%s < 0) ^ (%s < 0)) {" % ( @@ -5772,3 +5783,10 @@ static int __Pyx_cdivision_warning(void) { 'MODULENAME': Naming.modulename_cname, 'LINENO': Naming.lineno_cname, }) + +# from intobject.c +division_overflow_test_code = UtilityCode( +proto=""" +#define UNARY_NEG_WOULD_OVERFLOW(x) \ + (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x))) +""") diff --git a/tests/run/cdivision_CEP_516.pyx b/tests/run/cdivision_CEP_516.pyx index 82a55139..9866594e 100644 --- a/tests/run/cdivision_CEP_516.pyx +++ b/tests/run/cdivision_CEP_516.pyx @@ -64,6 +64,14 @@ verbose_call(5) 'float division' >>> mod_div_zero_float(25, 0, 0) 'float divmod()' + +>>> import sys +>>> py_div_long(-5, -1) +5 +>>> py_div_long(-sys.maxint-1, -1) +Traceback (most recent call last): +... +OverflowError: value too large to perform division """ cimport cython @@ -147,3 +155,7 @@ def mod_div_zero_float(float a, float b, float c): return (a % b) / c except ZeroDivisionError, ex: return ex.message + +@cython.cdivision(False) +def py_div_long(long a, long b): + return a / b -- 2.26.2