Author: Armin Rigo <[email protected]>
Branch:
Changeset: r84091:5e6d2531c7c9
Date: 2016-05-01 11:35 +0200
http://bitbucket.org/pypy/pypy/changeset/5e6d2531c7c9/
Log: Fix PyString_Concat and PyString_ConcatAndDel to do the right thing
with reference counts (I think)
diff --git a/pypy/module/cpyext/bytesobject.py
b/pypy/module/cpyext/bytesobject.py
--- a/pypy/module/cpyext/bytesobject.py
+++ b/pypy/module/cpyext/bytesobject.py
@@ -6,7 +6,7 @@
from pypy.module.cpyext.pyerrors import PyErr_BadArgument
from pypy.module.cpyext.pyobject import (
PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
- make_typedescr, get_typedescr, as_pyobj, Py_IncRef)
+ make_typedescr, get_typedescr, as_pyobj, Py_IncRef, get_w_obj_and_decref)
##
## Implementation of PyStringObject
@@ -233,7 +233,7 @@
def _PyString_Eq(space, w_str1, w_str2):
return space.eq_w(w_str1, w_str2)
-@cpython_api([PyObjectP, PyObject], lltype.Void)
+@cpython_api([PyObjectP, PyObject], lltype.Void, error=None)
def PyString_Concat(space, ref, w_newpart):
"""Create a new string object in *string containing the contents of newpart
appended to string; the caller will own the new reference. The reference
to
@@ -241,26 +241,27 @@
the old reference to string will still be discarded and the value of
*string will be set to NULL; the appropriate exception will be set."""
- if not ref[0]:
+ old = ref[0]
+ if not old:
return
- if w_newpart is None or not PyString_Check(space, ref[0]) or not \
- (space.isinstance_w(w_newpart, space.w_str) or
- space.isinstance_w(w_newpart, space.w_unicode)):
- Py_DecRef(space, ref[0])
- ref[0] = lltype.nullptr(PyObject.TO)
- return
- w_str = from_ref(space, ref[0])
- w_newstr = space.add(w_str, w_newpart)
- ref[0] = make_ref(space, w_newstr)
- Py_IncRef(space, ref[0])
+ ref[0] = lltype.nullptr(PyObject.TO)
+ w_str = get_w_obj_and_decref(space, old)
+ if w_newpart is not None and PyString_Check(space, old):
+ # xxx if w_newpart is not a string or unicode or bytearray,
+ # this might call __radd__() on it, whereas CPython raises
+ # a TypeError in this case.
+ w_newstr = space.add(w_str, w_newpart)
+ ref[0] = make_ref(space, w_newstr)
-@cpython_api([PyObjectP, PyObject], lltype.Void)
+@cpython_api([PyObjectP, PyObject], lltype.Void, error=None)
def PyString_ConcatAndDel(space, ref, newpart):
"""Create a new string object in *string containing the contents of newpart
appended to string. This version decrements the reference count of
newpart."""
- PyString_Concat(space, ref, newpart)
- Py_DecRef(space, newpart)
+ try:
+ PyString_Concat(space, ref, newpart)
+ finally:
+ Py_DecRef(space, newpart)
@cpython_api([PyObject, PyObject], PyObject)
def PyString_Format(space, w_format, w_args):
diff --git a/pypy/module/cpyext/test/test_bytesobject.py
b/pypy/module/cpyext/test/test_bytesobject.py
--- a/pypy/module/cpyext/test/test_bytesobject.py
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -359,6 +359,7 @@
assert space.str_w(from_ref(space, ptr[0])) == 'abcdef'
api.PyString_Concat(ptr, space.w_None)
assert not ptr[0]
+ api.PyErr_Clear()
ptr[0] = lltype.nullptr(PyObject.TO)
api.PyString_Concat(ptr, space.wrap('def')) # should not crash
lltype.free(ptr, flavor='raw')
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit