Files
Victor Stinner 8356e9c721 [3.14] gh-158585: Fix _PyBytes_Resize() if hash value is already computed (#159585)
* [3.15] gh-158585: Fix _PyBytes_Resize() if hash value is already computed (#159555)

* gh-158585: Fix _PyBytes_Resize() if hash value is already computed (#158589)

_PyBytes_Resize() now creates a new bytes object if the hash value
was already computed.

bytes_resize_inplace() no longer sets the hash value to -1, since
this function must not be called if the hash value was already
computed.

Add tests on PyUnicode_Resize().

(cherry picked from commit 6e7738bb5e)

* gh-158585: Fix refleak in _testcapi.bytes_resize() (#158806)

(cherry picked from commit 587b7a5b31)
(cherry picked from commit 251278d5ee)

* Adjust code for 3.14
2026-10-16 22:09:04 +00:00

86 lines
1.9 KiB
C

#include "parts.h"
#include "util.h"
/* Test _PyBytes_Resize() */
static PyObject *
bytes_resize(PyObject *Py_UNUSED(module), PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = {"obj", "newsize", "new", "compute_hash", NULL};
PyObject *obj;
Py_ssize_t newsize;
int new;
int compute_hash = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"Onp|p", kwlist,
&obj, &newsize, &new, &compute_hash)) {
return NULL;
}
NULLABLE(obj);
if (new) {
assert(obj != NULL);
assert(PyBytes_CheckExact(obj));
PyObject *newobj = PyBytes_FromStringAndSize(NULL, PyBytes_Size(obj));
if (newobj == NULL) {
return NULL;
}
memcpy(PyBytes_AsString(newobj), PyBytes_AsString(obj), PyBytes_Size(obj));
obj = newobj;
}
else {
Py_XINCREF(obj);
}
if (compute_hash) {
if (PyObject_Hash(obj) == -1) {
Py_DECREF(obj);
return NULL;
}
}
PyObject *old_obj = obj;
if (_PyBytes_Resize(&obj, newsize) < 0) {
assert(obj == NULL);
return NULL;
}
else {
assert(obj != NULL);
}
Py_ssize_t refcnt = Py_REFCNT(obj);
return Py_BuildValue("Nnp", obj, refcnt, obj != old_obj);
}
/* Test PyBytes_Join() */
static PyObject *
bytes_join(PyObject *Py_UNUSED(module), PyObject *args)
{
PyObject *sep, *iterable;
if (!PyArg_ParseTuple(args, "OO", &sep, &iterable)) {
return NULL;
}
NULLABLE(sep);
NULLABLE(iterable);
return PyBytes_Join(sep, iterable);
}
static PyMethodDef test_methods[] = {
{"bytes_resize", _PyCFunction_CAST(bytes_resize), METH_VARARGS | METH_KEYWORDS},
{"bytes_join", bytes_join, METH_VARARGS},
{NULL},
};
int
_PyTestCapi_Init_Bytes(PyObject *m)
{
if (PyModule_AddFunctions(m, test_methods) < 0) {
return -1;
}
return 0;
}