Permalink
Browse files

guard against incorrect values for PYLONG_BITS_IN_DIGIT that do not m…

…atch CPython's
  • Loading branch information...
1 parent 900dfde commit 67c64fe1314eea3eb15c7e299038f70c294104bf @scoder scoder committed Mar 9, 2013
Showing with 27 additions and 0 deletions.
  1. +21 −0 Cython/Compiler/ModuleNode.py
  2. +6 −0 Cython/Compiler/PyrexTypes.py
@@ -506,6 +506,27 @@ def generate_module_preamble(self, env, cimported_modules, code):
code.putln("/* Generated by Cython %s */" % Version.watermark)
code.putln("")
code.putln("#define PY_SSIZE_T_CLEAN")
+
+ # sizeof(PyLongObject.ob_digit[0]) may have been determined dynamically
+ # at compile time in CPython, in which case we can't know the correct
+ # storage size for an installed system. We can rely on it only if
+ # pyconfig.h defines it statically, i.e. if it was set by "configure".
+ # Once we include "Python.h", it will come up with its own idea about
+ # a suitable value, which may or may not match the real one.
+ code.putln("#ifndef CYTHON_USE_PYLONG_INTERNALS")
+ code.putln("#ifdef PYLONG_BITS_IN_DIGIT")
+ # assume it's an incorrect left-over
+ code.putln("#define CYTHON_USE_PYLONG_INTERNALS 0")
+ code.putln("#else")
+ code.putln('#include "pyconfig.h"')
+ code.putln("#ifdef PYLONG_BITS_IN_DIGIT")
+ code.putln("#define CYTHON_USE_PYLONG_INTERNALS 1")
+ code.putln("#else")
+ code.putln("#define CYTHON_USE_PYLONG_INTERNALS 0")
+ code.putln("#endif")
+ code.putln("#endif")
+ code.putln("#endif")
+
for filename in env.python_include_files:
code.putln('#include "%s"' % filename)
code.putln("#ifndef Py_PYTHON_H")
@@ -1386,8 +1386,10 @@ def py_type_name(self):
""",
impl="""
#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
#include "longintrepr.h"
#endif
+#endif
static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) {
const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
const int is_unsigned = neg_one > const_zero;
@@ -1405,13 +1407,15 @@ def py_type_name(self):
if (likely(PyLong_Check(x))) {
if (is_unsigned) {
#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
if (sizeof(digit) <= sizeof(%(type)s)) {
switch (Py_SIZE(x)) {
case 0: return 0;
case 1: return (%(type)s) ((PyLongObject*)x)->ob_digit[0];
}
}
#endif
+#endif
if (unlikely(Py_SIZE(x) < 0)) {
PyErr_SetString(PyExc_OverflowError,
"can't convert negative value to %(type)s");
@@ -1420,6 +1424,7 @@ def py_type_name(self):
return (%(type)s)PyLong_AsUnsigned%(TypeName)s(x);
} else {
#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
if (sizeof(digit) <= sizeof(%(type)s)) {
switch (Py_SIZE(x)) {
case 0: return 0;
@@ -1428,6 +1433,7 @@ def py_type_name(self):
}
}
#endif
+#endif
return (%(type)s)PyLong_As%(TypeName)s(x);
}
} else {

0 comments on commit 67c64fe

Please sign in to comment.