Skip to content

Commit df1a0fc

Browse files
[3.15] gh-159430: Add _PyObject_LookupSpecial error checks in bytes/weakref (GH-159432) (GH-159474)
gh-159430: Add _PyObject_LookupSpecial error checks in bytes/weakref (GH-159432) _PyObject_LookupSpecial needs a PyErr_Occurred() check to handle failures while during the lookup, or else it can fail with a "returned a result with an exception set" error. Add some missing ones in bytes and weakref/ (cherry picked from commit 3646ea5) Co-authored-by: Michael J. Sullivan <sully@msully.net>
1 parent cb7a629 commit df1a0fc

6 files changed

Lines changed: 35 additions & 0 deletions

File tree

‎Lib/test/test_bytes.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,19 @@ def test_memory_leak_gh_140939(self):
901901
b = self.type2test(b'%*b')
902902
b % (_testcapi.PY_SSIZE_T_MAX, b'abc')
903903

904+
def test_mod_bytes_lookup_error(self):
905+
# An error raised while looking up __bytes__ propagates.
906+
class BadBytes:
907+
@property
908+
def __bytes__(self):
909+
raise ZeroDivisionError
910+
def __buffer__(self, flags):
911+
return memoryview(b'abc')
912+
913+
b = self.type2test(b'%b')
914+
with self.assertRaises(ZeroDivisionError):
915+
b % BadBytes()
916+
904917
def test_imod(self):
905918
b = self.type2test(b'hello, %b!')
906919
orig = b

‎Lib/test/test_weakref.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,17 @@ def __getattr__(self, x):
162162
self.assertIn('MyConfig', repr(obj_weakref))
163163
self.assertIn('MyConfig', str(obj_weakref))
164164

165+
def test_repr_name_lookup_error(self):
166+
# An error raised while looking up __name__ propagates.
167+
class BadName:
168+
@property
169+
def __name__(self):
170+
raise ZeroDivisionError
171+
172+
obj = BadName()
173+
with self.assertRaises(ZeroDivisionError):
174+
repr(weakref.ref(obj))
175+
165176
def test_basic_callback(self):
166177
self.check_basic_callback(C)
167178
self.check_basic_callback(create_function)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Report the correct exception if looking up :meth:`~object.__bytes__` raises
2+
an exception while performing %-formatting of :class:`bytes`.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Report the correct exception if looking up ``__name__`` raises an exception
2+
when calling :func:`repr` on a :class:`weakref.ref`.

‎Objects/bytesobject.c‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,9 @@ format_obj(PyObject *v, Py_ssize_t argidx, PyObject *key,
592592
*plen = PyBytes_GET_SIZE(result);
593593
return result;
594594
}
595+
else if (PyErr_Occurred()) {
596+
return NULL;
597+
}
595598
/* does it support buffer protocol? */
596599
if (PyObject_CheckBuffer(v)) {
597600
/* maybe we can avoid making a copy of the buffer object here? */

‎Objects/weakrefobject.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ weakref_repr(PyObject *self)
221221
}
222222

223223
PyObject *name = _PyObject_LookupSpecial(obj, &_Py_ID(__name__));
224+
if (name == NULL && PyErr_Occurred()) {
225+
Py_DECREF(obj);
226+
return NULL;
227+
}
224228
PyObject *repr;
225229
if (name == NULL || !PyUnicode_Check(name)) {
226230
repr = PyUnicode_FromFormat(

0 commit comments

Comments
 (0)