mirror of
https://github.com/python/cpython.git
synced 2026-10-28 18:35:21 +08:00
* [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 commit6e7738bb5e) * gh-158585: Fix refleak in _testcapi.bytes_resize() (#158806) (cherry picked from commit587b7a5b31) (cherry picked from commit251278d5ee) * Adjust code for 3.14
86 lines
1.9 KiB
C
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;
|
|
}
|