mirror of
https://github.com/python/cpython.git
synced 2026-10-28 10:25:05 +08:00
gh-158334: Fix bytes.translate() when the input is returned unchanged (#158344)
Do no read output_start pointer after PyBytesWriter_Finish() since the pointer became a dangling pointer. Co-authored-by: Vyron Vasileiadis <hi@fedonman.com>
This commit is contained in:
1 parent
969af80daf
commit
b4be3a5804
2 files changed
+37
-5
No files matched your search
@@ -1147,6 +1147,34 @@ class BaseBytesTest:
|
||||
c = b.translate(None, delete=b'e')
|
||||
self.assertEqual(c, b'hllo')
|
||||
|
||||
# short inputs starting with NUL bytes
|
||||
table = bytes.maketrans(b'\x00', b'Z')
|
||||
for data in b'\x00', b'\x00' * 8, b'\x00' * 8 + b'a' * 247:
|
||||
c = self.type2test(data).translate(table)
|
||||
self.assertEqual(c, data.replace(b'\x00', b'Z'))
|
||||
|
||||
@support.cpython_only
|
||||
def test_translate_unchanged(self):
|
||||
if self.type2test != bytes:
|
||||
self.skipTest("test specific bytes.translate()")
|
||||
|
||||
# bytes.translate() returns the input string unchanged
|
||||
# if no byte is modified
|
||||
size = 1024
|
||||
b = b'hell' + b'o' * size
|
||||
rosetta = bytearray(range(256))
|
||||
rosetta[ord('#')] = ord('?')
|
||||
self.assertIs(b.translate(rosetta), b)
|
||||
|
||||
# bytes.translate() always create a new object
|
||||
# if the input string is a bytes subclass
|
||||
class bytes_subclass(bytes):
|
||||
pass
|
||||
b = bytes_subclass(b)
|
||||
result = b.translate(rosetta)
|
||||
self.assertIsNot(result, b)
|
||||
self.assertEqual(result, b)
|
||||
|
||||
def test_sq_item(self):
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
obj = self.type2test((42,))
|
||||
|
||||
@@ -2324,15 +2324,19 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table,
|
||||
c = Py_CHARMASK(*input++);
|
||||
*output++ = table_chars[c];
|
||||
}
|
||||
PyObject *result = PyBytesWriter_Finish(writer);
|
||||
|
||||
/* Check if anything changed (for returning original object) */
|
||||
/* We save this check until the end so that the compiler will */
|
||||
/* unroll the loop above leading to MUCH faster code. */
|
||||
if (result != NULL && PyBytes_CheckExact(input_obj)) {
|
||||
if (memcmp(PyBytes_AS_STRING(input_obj), output_start, inlen) == 0) {
|
||||
Py_SETREF(result, Py_NewRef(input_obj));
|
||||
}
|
||||
PyObject *result;
|
||||
if (PyBytes_CheckExact(input_obj)
|
||||
&& memcmp(PyBytes_AS_STRING(input_obj), output_start, inlen) == 0)
|
||||
{
|
||||
PyBytesWriter_Discard(writer);
|
||||
result = Py_NewRef(input_obj);
|
||||
}
|
||||
else {
|
||||
result = PyBytesWriter_Finish(writer);
|
||||
}
|
||||
|
||||
PyBuffer_Release(&del_table_view);
|
||||
|
||||
Reference in new issue
Block a user