-
-
Notifications
You must be signed in to change notification settings - Fork 33.8k
gh-143308: fix UAF when PickleBuffer is concurrently mutated in a callback #143312
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
1e4c48f
f359533
4129734
a6a5713
a6a3a91
b2117f5
ec61e9c
47396ab
fbc62c5
334cc62
0d70297
fc01ce1
170b73f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| :mod:`pickle`: fix use-after-free crashes when a :class:`~pickle.PickleBuffer` | ||
| is concurrently mutated by a custom buffer callback during pickling. | ||
| Patch by Bénédikt Tran and Aaron Wieczorek. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2646,43 +2646,58 @@ save_picklebuffer(PickleState *st, PicklerObject *self, PyObject *obj) | |
| "pointing to a non-contiguous buffer"); | ||
| return -1; | ||
| } | ||
|
|
||
| int rc = 0; | ||
| Py_buffer keepalive_view; // to ensure that 'view' is kept alive | ||
| if (PyObject_GetBuffer(view->obj, &keepalive_view, PyBUF_FULL_RO) != 0) { | ||
|
||
| return -1; | ||
| } | ||
|
|
||
| int in_band = 1; | ||
| if (self->buffer_callback != NULL) { | ||
| PyObject *ret = PyObject_CallOneArg(self->buffer_callback, obj); | ||
| if (ret == NULL) { | ||
| return -1; | ||
| goto error; | ||
| } | ||
| in_band = PyObject_IsTrue(ret); | ||
| Py_DECREF(ret); | ||
| if (in_band == -1) { | ||
| return -1; | ||
| goto error; | ||
| } | ||
| } | ||
| if (in_band) { | ||
| /* Write data in-band */ | ||
| if (view->readonly) { | ||
| return _save_bytes_data(st, self, obj, (const char *)view->buf, | ||
| rc = _save_bytes_data(st, self, obj, (const char *)view->buf, | ||
| view->len); | ||
| } | ||
| else { | ||
| return _save_bytearray_data(st, self, obj, (const char *)view->buf, | ||
| rc = _save_bytearray_data(st, self, obj, (const char *)view->buf, | ||
| view->len); | ||
| } | ||
| goto exit; | ||
| } | ||
| else { | ||
| /* Write data out-of-band */ | ||
| const char next_buffer_op = NEXT_BUFFER; | ||
| if (_Pickler_Write(self, &next_buffer_op, 1) < 0) { | ||
| return -1; | ||
| goto error; | ||
| } | ||
| if (view->readonly) { | ||
| const char readonly_buffer_op = READONLY_BUFFER; | ||
| if (_Pickler_Write(self, &readonly_buffer_op, 1) < 0) { | ||
| return -1; | ||
| goto error; | ||
| } | ||
| } | ||
| } | ||
| return 0; | ||
|
|
||
| exit: | ||
| PyBuffer_Release(&keepalive_view); | ||
| return rc; | ||
|
|
||
| error: | ||
| PyBuffer_Release(&keepalive_view); | ||
| return -1; | ||
| } | ||
|
|
||
| /* A copy of PyUnicode_AsRawUnicodeEscapeString() that also translates | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.