[pypy-commit] pypy default: add slot definitions for __len__, __setitem__, __delitem__, avoid crash in PyDict_Next

mattip pypy.commits at gmail.com
Tue May 16 06:54:32 EDT 2017


Author: Matti Picus <matti.picus at gmail.com>
Branch: 
Changeset: r91311:fbcdfc92a521
Date: 2017-05-16 13:52 +0300
http://bitbucket.org/pypy/pypy/changeset/fbcdfc92a521/

Log:	add slot definitions for __len__, __setitem__, __delitem__, avoid
	crash in PyDict_Next

diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py
--- a/pypy/module/cpyext/dictobject.py
+++ b/pypy/module/cpyext/dictobject.py
@@ -257,7 +257,8 @@
 
     if w_dict is None:
         return 0
-
+    if not space.isinstance_w(w_dict, space.w_dict):
+        return 0 
     pos = ppos[0]
     py_obj = as_pyobj(space, w_dict)
     py_dict = rffi.cast(PyDictObject, py_obj)
@@ -268,6 +269,9 @@
         py_dict.c__tmpkeys = create_ref(space, w_keys)
         Py_IncRef(space, py_dict.c__tmpkeys)
     else:
+        if not py_dict.c__tmpkeys:
+            # pos should have been 0, cannot fail so return 0
+            return 0;
         w_keys = from_ref(space, py_dict.c__tmpkeys)
     ppos[0] += 1
     if pos >= space.len_w(w_keys):
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -14,7 +14,7 @@
     ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
     cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
     readbufferproc, getbufferproc, releasebufferproc, ssizessizeobjargproc)
-from pypy.module.cpyext.pyobject import make_ref, decref, as_pyobj
+from pypy.module.cpyext.pyobject import make_ref, decref, as_pyobj, from_ref
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.memoryobject import fill_Py_buffer
 from pypy.module.cpyext.state import State
@@ -265,7 +265,7 @@
     check_num_args(space, w_args, 1)
     args_w = space.fixedview(w_args)
     index = space.int_w(space.index(args_w[0]))
-    null = lltype.nullptr(PyObject.TO)
+    null = rffi.cast(PyObject, 0)
     res = generic_cpy_call(space, func_target, w_self, index, null)
     if rffi.cast(lltype.Signed, res) == -1:
         space.fromcache(State).check_and_raise_exception(always=True)
@@ -294,7 +294,8 @@
     func_target = rffi.cast(objobjargproc, func)
     check_num_args(space, w_args, 1)
     w_key, = space.fixedview(w_args)
-    res = generic_cpy_call(space, func_target, w_self, w_key, None)
+    null = rffi.cast(PyObject, 0)
+    res = generic_cpy_call(space, func_target, w_self, w_key, null)
     if rffi.cast(lltype.Signed, res) == -1:
         space.fromcache(State).check_and_raise_exception(always=True)
     return space.w_None
@@ -612,6 +613,8 @@
             handled = True
 
     for tp_name, attr in [('tp_hash', '__hash__'),
+                          ('tp_as_sequence.c_sq_length', '__len__'),
+                          ('tp_as_mapping.c_mp_length', '__len__'),
                          ]:
         if name == tp_name:
             slot_fn = w_type.getdictvalue(space, attr)
@@ -637,7 +640,8 @@
                           ('tp_as_number.c_nb_xor', '__xor__'),
                           ('tp_as_number.c_nb_or', '__or__'),
                           ('tp_as_sequence.c_sq_concat', '__add__'),
-                          ('tp_as_sequence.c_sq_inplace_concat', '__iadd__')
+                          ('tp_as_sequence.c_sq_inplace_concat', '__iadd__'),
+                          ('tp_as_mapping.c_mp_subscript', '__getitem__'),
                           ]:
         if name == tp_name:
             slot_fn = w_type.getdictvalue(space, attr)
@@ -651,7 +655,7 @@
             handled = True
 
     # binary-with-Py_ssize_t-type
-    for tp_name, attr in [('tp_as_sequence.c_sq_item', '__getitem'),
+    for tp_name, attr in [('tp_as_sequence.c_sq_item', '__getitem__'),
                           ('tp_as_sequence.c_sq_repeat', '__mul__'),
                           ('tp_as_sequence.c_sq_repeat', '__mul__'),
                           ('tp_as_sequence.c_sq_inplace_repeat', '__imul__'),
@@ -680,7 +684,48 @@
             def slot_func(space, w_self, w_arg1, w_arg2):
                 return space.call_function(slot_fn, w_self, w_arg1, w_arg2)
             handled = True
+    # ternary-with-void returning-Py_size_t-type
+    for tp_name, attr in [('tp_as_mapping.c_mp_ass_subscript', '__setitem__'),
+                         ]:
+        if name == tp_name:
+            slot_ass = w_type.getdictvalue(space, attr)
+            if slot_ass is None:
+                return
+            slot_del = w_type.getdictvalue(space, '__delitem__')
+            if slot_del is None:
+                return
 
+            @slot_function([PyObject, PyObject, PyObject], rffi.INT_real, error=-1)
+            @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
+            def slot_func(space, w_self, w_arg1, arg2):
+                if arg2:
+                    w_arg2 = from_ref(space, rffi.cast(PyObject, arg2))
+                    space.call_function(slot_ass, w_self, w_arg1, w_arg2)
+                else:
+                    space.call_function(slot_del, w_self, w_arg1)
+                return 0
+            handled = True
+    # ternary-Py_size_t-void returning-Py_size_t-type
+    for tp_name, attr in [('tp_as_sequence.c_sq_ass_item', '__setitem__'),
+                         ]:
+        if name == tp_name:
+            slot_ass = w_type.getdictvalue(space, attr)
+            if slot_ass is None:
+                return
+            slot_del = w_type.getdictvalue(space, '__delitem__')
+            if slot_del is None:
+                return
+
+            @slot_function([PyObject, lltype.Signed, PyObject], rffi.INT_real, error=-1)
+            @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
+            def slot_func(space, w_self, arg1, arg2):
+                if arg2:
+                    w_arg2 = from_ref(space, rffi.cast(PyObject, arg2))
+                    space.call_function(slot_ass, w_self, space.newint(arg1), w_arg2)
+                else:
+                    space.call_function(slot_del, w_self, space.newint(arg1))
+                return 0
+            handled = True
     if handled:
         pass
     elif name == 'tp_setattro':


More information about the pypy-commit mailing list