[pypy-svn] r79849 - in pypy/trunk/pypy/module/cpyext: . src test

arigo at codespeak.net arigo at codespeak.net
Mon Dec 6 16:39:13 CET 2010


Author: arigo
Date: Mon Dec  6 16:39:11 2010
New Revision: 79849

Modified:
   pypy/trunk/pypy/module/cpyext/intobject.py
   pypy/trunk/pypy/module/cpyext/src/getargs.c
   pypy/trunk/pypy/module/cpyext/test/test_intobject.py
Log:
Allow calls to PyInt_AsLong(NULL), and raise TypeError.


Modified: pypy/trunk/pypy/module/cpyext/intobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/intobject.py	(original)
+++ pypy/trunk/pypy/module/cpyext/intobject.py	Mon Dec  6 16:39:11 2010
@@ -1,5 +1,6 @@
 
 from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.interpreter.error import OperationError
 from pypy.module.cpyext.api import (cpython_api, PyObject, CANNOT_FAIL,
                                     build_type_checkers, Py_ssize_t)
 
@@ -19,6 +20,9 @@
     already one, and then return its value. If there is an error, -1 is
     returned, and the caller should check PyErr_Occurred() to find out whether
     there was an error, or whether the value just happened to be -1."""
+    if w_obj is None:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("an integer is required, got NULL"))
     return space.int_w(space.int(w_obj))
 
 @cpython_api([PyObject], lltype.Unsigned, error=-1)
@@ -26,6 +30,9 @@
     """Return a C unsigned long representation of the contents of pylong.
     If pylong is greater than ULONG_MAX, an OverflowError is
     raised."""
+    if w_obj is None:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("an integer is required, got NULL"))
     return space.uint_w(space.int(w_obj))
 
 @cpython_api([PyObject], lltype.Signed, error=CANNOT_FAIL)
@@ -39,6 +46,9 @@
     PyLongObject, if it is not already one, and then return its value as
     Py_ssize_t.
     """
+    if w_obj is None:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("an integer is required, got NULL"))
     return space.int_w(w_obj) # XXX this is wrong on win64
 
 @cpython_api([Py_ssize_t], PyObject)
@@ -48,4 +58,3 @@
     returned.
     """
     return space.wrap(ival) # XXX this is wrong on win64
-

Modified: pypy/trunk/pypy/module/cpyext/src/getargs.c
==============================================================================
--- pypy/trunk/pypy/module/cpyext/src/getargs.c	(original)
+++ pypy/trunk/pypy/module/cpyext/src/getargs.c	Mon Dec  6 16:39:11 2010
@@ -445,18 +445,22 @@
 	for (i = 0; i < n; i++) {
 		char *msg;
 		PyObject *item;
-		item = PySequence_GetItem(arg, i);
+		/* CPython uses PySequence_GetItem() and Py_XDECREF() here,
+		   exposing a crash (see http://bugs.python.org/issue6083).
+		   It always crashes with PyPy, so we apply the fix being
+		   discussed: we only allow a tuple. */
+		item = PyTuple_GetItem(arg, i);
 		if (item == NULL) {
 			PyErr_Clear();
 			levels[0] = i+1;
 			levels[1] = 0;
-			strncpy(msgbuf, "is not retrievable", bufsize);
+			strncpy(msgbuf, "is not retrievable (subargument "
+				        "must be a real tuple with PyPy)",
+				        bufsize);
 			return msgbuf;
 		}
 		msg = convertitem(item, &format, p_va, flags, levels+1, 
 				  msgbuf, bufsize, freelist);
-		/* PySequence_GetItem calls tp->sq_item, which INCREFs */
-		Py_XDECREF(item);
 		if (msg != NULL) {
 			levels[0] = i+1;
 			return msg;

Modified: pypy/trunk/pypy/module/cpyext/test/test_intobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_intobject.py	(original)
+++ pypy/trunk/pypy/module/cpyext/test/test_intobject.py	Mon Dec  6 16:39:11 2010
@@ -19,6 +19,10 @@
         assert api.PyErr_Occurred() is space.w_TypeError
         api.PyErr_Clear()
 
+        assert api.PyInt_AsLong(None) == -1
+        assert api.PyErr_Occurred() is space.w_TypeError
+        api.PyErr_Clear()
+
         assert api.PyInt_AsUnsignedLong(space.wrap(sys.maxint)) == sys.maxint
         assert api.PyInt_AsUnsignedLong(space.wrap(-5)) == sys.maxint * 2 + 1
         assert api.PyErr_Occurred() is space.w_ValueError



More information about the Pypy-commit mailing list