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:
Victor StinnerandVyron Vasileiadis authored and GitHub committed 2026-09-29 12:17:17 +02:00
1 parent 969af80daf
commit b4be3a5804
2 files changed
+37 -5

No files matched your search

+28
View File
@@ -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,))
+9 -5
View File
@@ -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);