Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[3.13] gh-142560: prevent use-after-free in search-like methods by exporting buffer in bytearray (GH-142938)#142986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
cmaloney wants to merge1 commit intopython:3.13
base:3.13
Choose a base branch
Loading
fromcmaloney:backport-220f0b1-3.13
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletionsLib/test/test_bytes.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1897,6 +1897,37 @@ def __index__(self):
self.assertEqual(instance.ba[0], ord("?"), "Assigned bytearray not altered")
self.assertEqual(instance.new_ba, bytearray(0x180), "Wrong object altered")

def test_search_methods_reentrancy_raises_buffererror(self):
# gh-142560: Raise BufferError if buffer mutates during search arg conversion.
class Evil:
def __init__(self, ba):
self.ba = ba
def __buffer__(self, flags):
self.ba.clear()
return memoryview(self.ba)
def __release_buffer__(self, view: memoryview) -> None:
view.release()
def __index__(self):
self.ba.clear()
return ord("A")

def make_case():
ba = bytearray(b"A")
return ba, Evil(ba)

for name in ("find", "count", "index", "rindex", "rfind"):
ba, evil = make_case()
with self.subTest(name):
with self.assertRaises(BufferError):
getattr(ba, name)(evil)

ba, evil = make_case()
with self.assertRaises(BufferError):
evil in ba
with self.assertRaises(BufferError):
ba.split(evil)
with self.assertRaises(BufferError):
ba.rsplit(evil)

class AssortedBytesTest(unittest.TestCase):
#
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Fix use-after-free in:class:`bytearray` search-like methods (:meth:`~bytearray.find`,:meth:`~bytearray.count`,:meth:`~bytearray.index`,:meth:`~bytearray.rindex`, and:meth:`~bytearray.rfind`) by marking the storage as exported which causes reallocation attempts to raise:exc:`BufferError`. For:func:`~operator.contains`,:meth:`~bytearray.split`, and:meth:`~bytearray.rsplit` the:ref:`buffer protocol<bufferobjects>` is used for this.
119 changes: 78 additions & 41 deletionsObjects/bytearrayobject.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,8 +64,29 @@
assert(obj->ob_exports >= 0);
}

typedef PyObject* (*_ba_bytes_op)(const char *buf, Py_ssize_t len,
PyObject *sub, Py_ssize_t start,
Py_ssize_t end);

static PyObject *
_bytearray_with_buffer(PyByteArrayObject *self, _ba_bytes_op op, PyObject *sub,
Py_ssize_t start, Py_ssize_t end)
{
PyObject *res;

Py_BEGIN_CRITICAL_SECTION(self);

/* Increase exports to prevent bytearray storage from changing during op. */
self->ob_exports++;
res = op(PyByteArray_AS_STRING(self), Py_SIZE(self), sub, start, end);
self->ob_exports--;
Py_END_CRITICAL_SECTION(self);

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.1.7)

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.1.7)

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 1.1.1w)

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 1.1.1w)

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.2.6)

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.2.6)

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.3.5)

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.3.5)

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.0.18)

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.0.18)

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Hypothesis tests on Ubuntu

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Hypothesis tests on Ubuntu

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Address sanitizer (ubuntu-24.04)

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Address sanitizer (ubuntu-24.04)

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu (free-threading) / build and test (ubuntu-24.04)

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu (free-threading) / build and test (ubuntu-24.04)

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu / build and test (ubuntu-24.04)

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu / build and test (ubuntu-24.04)

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu (free-threading) / build and test (ubuntu-24.04-arm)

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu (free-threading) / build and test (ubuntu-24.04-arm)

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu / build and test (ubuntu-24.04-arm)

‘Py_END_CRITICAL_SECTION’ undeclared (first use in this function)

Check failure on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu / build and test (ubuntu-24.04-arm)

macro "Py_END_CRITICAL_SECTION" passed 1 arguments, but takes just 0

Check warning on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Windows / build (arm64)

too many arguments for function-like macro invocation 'Py_END_CRITICAL_SECTION' [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check warning on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Windows / build (arm64)

too many arguments for function-like macro invocation 'Py_END_CRITICAL_SECTION' [D:\a\cpython\cpython\PCbuild\_freeze_module.vcxproj]

Check warning on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Windows (free-threading) / build (arm64)

too many arguments for function-like macro invocation 'Py_END_CRITICAL_SECTION' [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check warning on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Windows (free-threading) / build (arm64)

too many arguments for function-like macro invocation 'Py_END_CRITICAL_SECTION' [D:\a\cpython\cpython\PCbuild\_freeze_module.vcxproj]

Check warning on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Windows / build and test (x64)

too many arguments for function-like macro invocation 'Py_END_CRITICAL_SECTION' [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check warning on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Windows / build and test (x64)

too many arguments for function-like macro invocation 'Py_END_CRITICAL_SECTION' [D:\a\cpython\cpython\PCbuild\_freeze_module.vcxproj]

Check warning on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Windows (free-threading) / build and test (x64)

too many arguments for function-like macro invocation 'Py_END_CRITICAL_SECTION' [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check warning on line 83 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Windows (free-threading) / build and test (x64)

too many arguments for function-like macro invocation 'Py_END_CRITICAL_SECTION' [D:\a\cpython\cpython\PCbuild\_freeze_module.vcxproj]

return res;
}

static int
_canresize(PyByteArrayObject *self)

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.1.7)

invalid storage class for function ‘_canresize’

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 1.1.1w)

invalid storage class for function ‘_canresize’

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.2.6)

invalid storage class for function ‘_canresize’

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.3.5)

invalid storage class for function ‘_canresize’

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu SSL tests with OpenSSL (ubuntu-24.04, 3.0.18)

invalid storage class for function ‘_canresize’

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Hypothesis tests on Ubuntu

invalid storage class for function ‘_canresize’

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Address sanitizer (ubuntu-24.04)

invalid storage class for function ‘_canresize’

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu (free-threading) / build and test (ubuntu-24.04)

invalid storage class for function ‘_canresize’

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu / build and test (ubuntu-24.04)

invalid storage class for function ‘_canresize’

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu (free-threading) / build and test (ubuntu-24.04-arm)

invalid storage class for function ‘_canresize’

Check failure on line 89 in Objects/bytearrayobject.c

View workflow job for this annotation

GitHub Actions/ Ubuntu / build and test (ubuntu-24.04-arm)

invalid storage class for function ‘_canresize’
{
if (self->ob_exports > 0) {
PyErr_SetString(PyExc_BufferError,
Expand DownExpand Up@@ -1146,8 +1167,7 @@
Py_ssize_t end)
/*[clinic end generated code: output=413e1cab2ae87da0 input=793dfad803e2952f]*/
{
return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
sub, start, end);
return _bytearray_with_buffer(self, _Py_bytes_find, sub, start, end);
}

/*[clinic input]
Expand All@@ -1161,8 +1181,7 @@
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=a21ee2692e4f1233 input=4deb529db38deda8]*/
{
return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
sub, start, end);
return _bytearray_with_buffer(self, _Py_bytes_count, sub, start, end);
}

/*[clinic input]
Expand DownExpand Up@@ -1207,8 +1226,7 @@
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=067a1e78efc672a7 input=8cbaf6836dbd2a9a]*/
{
return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
sub, start, end);
return _bytearray_with_buffer(self, _Py_bytes_index, sub, start, end);
}

/*[clinic input]
Expand All@@ -1224,8 +1242,7 @@
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=51bf886f932b283c input=eaa107468a158423]*/
{
return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
sub, start, end);
return _bytearray_with_buffer(self, _Py_bytes_rfind, sub, start, end);
}

/*[clinic input]
Expand All@@ -1241,14 +1258,24 @@
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=38e1cf66bafb08b9 input=81cf49d0af4d5bd0]*/
{
return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
sub, start, end);
return _bytearray_with_buffer(self, _Py_bytes_rindex, sub, start, end);
}

static int
bytearray_contains(PyObject *self, PyObject *arg)
{
return _Py_bytes_contains(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), arg);
int ret = -1;
Py_BEGIN_CRITICAL_SECTION(self);
PyByteArrayObject *ba = _PyByteArray_CAST(self);

/* Increase exports to prevent bytearray storage from changing during _Py_bytes_contains(). */
ba->ob_exports++;
ret = _Py_bytes_contains(PyByteArray_AS_STRING(ba),
PyByteArray_GET_SIZE(self),
arg);
ba->ob_exports--;
Py_END_CRITICAL_SECTION();
return ret;
}

/*[clinic input]
Expand All@@ -1271,8 +1298,7 @@
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=a3d9b6d44d3662a6 input=76385e0b376b45c1]*/
{
return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
subobj, start, end);
return _bytearray_with_buffer(self, _Py_bytes_startswith, subobj, start, end);
}

/*[clinic input]
Expand All@@ -1295,8 +1321,7 @@
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=e75ea8c227954caa input=9b8baa879aa3d74b]*/
{
return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
subobj, start, end);
return _bytearray_with_buffer(self, _Py_bytes_endswith, subobj, start, end);
}

/*[clinic input]
Expand DownExpand Up@@ -1539,26 +1564,32 @@
Py_ssize_t maxsplit)
/*[clinic end generated code: output=833e2cf385d9a04d input=24f82669f41bf523]*/
{
Py_ssize_t len = PyByteArray_GET_SIZE(self), n;
const char *s = PyByteArray_AS_STRING(self), *sub;
PyObject *list;
Py_buffer vsub;
PyObject *list = NULL;

/* Increase exports to prevent bytearray storage from changing during _Py_bytes_contains(). */
self->ob_exports++;
const char *sbuf = PyByteArray_AS_STRING(self);
Py_ssize_t slen = PyByteArray_GET_SIZE((PyObject *)self);

if (maxsplit < 0)
maxsplit = PY_SSIZE_T_MAX;

if (sep == Py_None)
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
if (sep == Py_None) {
list = stringlib_split_whitespace((PyObject*)self, sbuf, slen, maxsplit);
goto done;
}

if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
Py_buffervsub;
if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) {
goto done;
}

list = stringlib_split(
(PyObject*) self, s, len, sub, n, maxsplit
);
list = stringlib_split((PyObject*)self, sbuf, slen,
(const char *)vsub.buf, vsub.len, maxsplit);
PyBuffer_Release(&vsub);

done:
self->ob_exports--;
return list;
}

Expand DownExpand Up@@ -1650,26 +1681,32 @@
Py_ssize_t maxsplit)
/*[clinic end generated code: output=a55e0b5a03cb6190 input=a68286e4dd692ffe]*/
{
Py_ssize_t len = PyByteArray_GET_SIZE(self), n;
const char *s = PyByteArray_AS_STRING(self), *sub;
PyObject *list;
Py_buffer vsub;
PyObject *list = NULL;

/* Increase exports to prevent bytearray storage from changing during _Py_bytes_contains(). */
self->ob_exports++;
const char *sbuf = PyByteArray_AS_STRING(self);
Py_ssize_t slen = PyByteArray_GET_SIZE((PyObject *)self);

if (maxsplit < 0)
maxsplit = PY_SSIZE_T_MAX;

if (sep == Py_None)
return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
if (sep == Py_None) {
list = stringlib_rsplit_whitespace((PyObject*)self, sbuf, slen, maxsplit);
goto done;
}

if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
Py_buffervsub;
if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) {
goto done;
}

list = stringlib_rsplit(
(PyObject*) self, s, len, sub, n, maxsplit
);
list = stringlib_rsplit((PyObject*)self, sbuf, slen,
(const char *)vsub.buf, vsub.len, maxsplit);
PyBuffer_Release(&vsub);

done:
self->ob_exports--;
return list;
}

Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp