mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
gh-98783: Fix crashes when str
subclasses are used in _PyUnicode_Equal
(#98806)
This commit is contained in:
parent
3ac8c0ab6e
commit
76f989dc3e
5 changed files with 36 additions and 3 deletions
|
@ -945,7 +945,7 @@ PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*);
|
||||||
and where the hash values are equal (i.e. a very probable match) */
|
and where the hash values are equal (i.e. a very probable match) */
|
||||||
PyAPI_FUNC(int) _PyUnicode_EQ(PyObject *, PyObject *);
|
PyAPI_FUNC(int) _PyUnicode_EQ(PyObject *, PyObject *);
|
||||||
|
|
||||||
/* Equality check. Returns -1 on failure. */
|
/* Equality check. */
|
||||||
PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *, PyObject *);
|
PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *, PyObject *);
|
||||||
|
|
||||||
PyAPI_FUNC(int) _PyUnicode_WideCharString_Converter(PyObject *, void *);
|
PyAPI_FUNC(int) _PyUnicode_WideCharString_Converter(PyObject *, void *);
|
||||||
|
|
|
@ -1317,6 +1317,15 @@ order (MRO) for bases """
|
||||||
with self.assertRaisesRegex(AttributeError, "'X' object has no attribute 'a'"):
|
with self.assertRaisesRegex(AttributeError, "'X' object has no attribute 'a'"):
|
||||||
X().a
|
X().a
|
||||||
|
|
||||||
|
# Test string subclass in `__slots__`, see gh-98783
|
||||||
|
class SubStr(str):
|
||||||
|
pass
|
||||||
|
class X(object):
|
||||||
|
__slots__ = (SubStr('x'),)
|
||||||
|
X().x = 1
|
||||||
|
with self.assertRaisesRegex(AttributeError, "'X' object has no attribute 'a'"):
|
||||||
|
X().a
|
||||||
|
|
||||||
def test_slots_special(self):
|
def test_slots_special(self):
|
||||||
# Testing __dict__ and __weakref__ in __slots__...
|
# Testing __dict__ and __weakref__ in __slots__...
|
||||||
class D(object):
|
class D(object):
|
||||||
|
@ -3589,6 +3598,16 @@ order (MRO) for bases """
|
||||||
self.assertEqual(o.__str__(), '41')
|
self.assertEqual(o.__str__(), '41')
|
||||||
self.assertEqual(o.__repr__(), 'A repr')
|
self.assertEqual(o.__repr__(), 'A repr')
|
||||||
|
|
||||||
|
def test_repr_with_module_str_subclass(self):
|
||||||
|
# gh-98783
|
||||||
|
class StrSub(str):
|
||||||
|
pass
|
||||||
|
class Some:
|
||||||
|
pass
|
||||||
|
Some.__module__ = StrSub('example')
|
||||||
|
self.assertIsInstance(repr(Some), str) # should not crash
|
||||||
|
self.assertIsInstance(repr(Some()), str) # should not crash
|
||||||
|
|
||||||
def test_keyword_arguments(self):
|
def test_keyword_arguments(self):
|
||||||
# Testing keyword arguments to __init__, __call__...
|
# Testing keyword arguments to __init__, __call__...
|
||||||
def f(a): return a
|
def f(a): return a
|
||||||
|
|
|
@ -1334,6 +1334,12 @@ class LongTest(unittest.TestCase):
|
||||||
b'\xff\xff\xff\xff\xff')
|
b'\xff\xff\xff\xff\xff')
|
||||||
self.assertRaises(OverflowError, (1).to_bytes, 0, 'big')
|
self.assertRaises(OverflowError, (1).to_bytes, 0, 'big')
|
||||||
|
|
||||||
|
# gh-98783
|
||||||
|
class SubStr(str):
|
||||||
|
pass
|
||||||
|
self.assertEqual((0).to_bytes(1, SubStr('big')), b'\x00')
|
||||||
|
self.assertEqual((0).to_bytes(0, SubStr('little')), b'')
|
||||||
|
|
||||||
def test_from_bytes(self):
|
def test_from_bytes(self):
|
||||||
def check(tests, byteorder, signed=False):
|
def check(tests, byteorder, signed=False):
|
||||||
def equivalent_python(byte_array, byteorder, signed=False):
|
def equivalent_python(byte_array, byteorder, signed=False):
|
||||||
|
@ -1534,6 +1540,12 @@ class LongTest(unittest.TestCase):
|
||||||
self.assertRaises(TypeError, int.from_bytes, MissingBytes())
|
self.assertRaises(TypeError, int.from_bytes, MissingBytes())
|
||||||
self.assertRaises(ZeroDivisionError, int.from_bytes, RaisingBytes())
|
self.assertRaises(ZeroDivisionError, int.from_bytes, RaisingBytes())
|
||||||
|
|
||||||
|
# gh-98783
|
||||||
|
class SubStr(str):
|
||||||
|
pass
|
||||||
|
self.assertEqual(int.from_bytes(b'', SubStr('big')), 0)
|
||||||
|
self.assertEqual(int.from_bytes(b'\x00', SubStr('little')), 0)
|
||||||
|
|
||||||
@support.cpython_only
|
@support.cpython_only
|
||||||
def test_from_bytes_small(self):
|
def test_from_bytes_small(self):
|
||||||
# bpo-46361
|
# bpo-46361
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix multiple crashes in debug mode when ``str`` subclasses
|
||||||
|
are used instead of ``str`` itself.
|
|
@ -10444,8 +10444,8 @@ unicode_compare_eq(PyObject *str1, PyObject *str2)
|
||||||
int
|
int
|
||||||
_PyUnicode_Equal(PyObject *str1, PyObject *str2)
|
_PyUnicode_Equal(PyObject *str1, PyObject *str2)
|
||||||
{
|
{
|
||||||
assert(PyUnicode_CheckExact(str1));
|
assert(PyUnicode_Check(str1));
|
||||||
assert(PyUnicode_CheckExact(str2));
|
assert(PyUnicode_Check(str2));
|
||||||
if (str1 == str2) {
|
if (str1 == str2) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue