-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
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
GH-59313: Do not allow incomplete tuples, or tuples with NULLs. #117747
Changes from 11 commits
d4d6f24
6a1f806
9aeb6da
40a49d6
0a06553
207005c
03643cf
0d8974e
8fad5a4
e4b4f39
f4c0a29
bf69fc5
4d0ad9e
269832a
3a766d8
003264f
a155802
ae437f1
03ce121
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 |
---|---|---|
|
@@ -30,6 +30,7 @@ static inline Py_ssize_t PyTuple_GET_SIZE(PyObject *op) { | |
static inline void | ||
PyTuple_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) { | ||
PyTupleObject *tuple = _PyTuple_CAST(op); | ||
assert(value != NULL); | ||
vstinner marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You modified PyTuple_SET_ITEM() but not PyTuple_SetItem(), is it on purpose? I suggest to modify both, since PyTuple_SetItem() doesn't call PyTuple_SET_ITEM(). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
assert(0 <= index); | ||
assert(index < Py_SIZE(tuple)); | ||
tuple->ob_item[index] = value; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Make sure that all tuple elements are valid and never NULL. Ensuring that | ||
tuples are always valid reduces the risk of cycle GC bugs and prevents | ||
``gc.get_referrers`` from returning invalid tuples. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2039,9 +2039,7 @@ | |
PySequence_Tuple(PyObject *v) | ||
{ | ||
PyObject *it; /* iter(v) */ | ||
Py_ssize_t n; /* guess for result tuple size */ | ||
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Address sanitizer
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Ubuntu SSL tests with OpenSSL (1.1.1w)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Hypothesis tests on Ubuntu
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Ubuntu SSL tests with OpenSSL (3.0.13)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Ubuntu SSL tests with OpenSSL (3.1.5)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Ubuntu SSL tests with OpenSSL (3.2.1)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Windows (free-threading) / build (arm64)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Windows (free-threading) / build (arm64)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Windows (free-threading) / build and test (x64)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Windows (free-threading) / build and test (x64)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Windows / build and test (x64)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Windows / build and test (x64)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Windows / build (arm64)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Windows / build (arm64)
Check warning on line 2042 in Objects/abstract.c GitHub Actions / Ubuntu / build and test
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a warning: unused variable ‘n’ [-Wunused-variable]
erlend-aasland marked this conversation as resolved.
Show resolved
Hide resolved
|
||
PyObject *result = NULL; | ||
Py_ssize_t j; | ||
|
||
if (v == NULL) { | ||
return null_error(); | ||
|
@@ -2063,57 +2061,31 @@ | |
if (it == NULL) | ||
return NULL; | ||
|
||
/* Guess result size and allocate space. */ | ||
n = PyObject_LengthHint(v, 10); | ||
if (n == -1) | ||
goto Fail; | ||
result = PyTuple_New(n); | ||
if (result == NULL) | ||
PyObject *temp = PyList_New(0); | ||
if (temp == NULL) | ||
goto Fail; | ||
|
||
/* Fill the tuple. */ | ||
for (j = 0; ; ++j) { | ||
/* Fill the temporary list. */ | ||
for (;;) { | ||
PyObject *item = PyIter_Next(it); | ||
if (item == NULL) { | ||
if (PyErr_Occurred()) | ||
if (PyErr_Occurred()) { | ||
Py_DECREF(temp); | ||
goto Fail; | ||
} | ||
break; | ||
} | ||
if (j >= n) { | ||
size_t newn = (size_t)n; | ||
/* The over-allocation strategy can grow a bit faster | ||
than for lists because unlike lists the | ||
over-allocation isn't permanent -- we reclaim | ||
the excess before the end of this routine. | ||
So, grow by ten and then add 25%. | ||
*/ | ||
newn += 10u; | ||
newn += newn >> 2; | ||
if (newn > PY_SSIZE_T_MAX) { | ||
/* Check for overflow */ | ||
PyErr_NoMemory(); | ||
Py_DECREF(item); | ||
goto Fail; | ||
} | ||
n = (Py_ssize_t)newn; | ||
if (_PyTuple_Resize(&result, n) != 0) { | ||
Py_DECREF(item); | ||
goto Fail; | ||
} | ||
if (_PyList_AppendTakeRef((PyListObject *)temp, item)) { | ||
Py_DECREF(temp); | ||
goto Fail; | ||
} | ||
PyTuple_SET_ITEM(result, j, item); | ||
} | ||
|
||
/* Cut tuple back if guess was too large. */ | ||
if (j < n && | ||
_PyTuple_Resize(&result, j) != 0) | ||
goto Fail; | ||
|
||
Py_DECREF(it); | ||
PyObject *result = _PyList_AsTupleTakeItems(temp); | ||
Py_DECREF(temp); | ||
return result; | ||
|
||
Fail: | ||
Py_XDECREF(result); | ||
Py_DECREF(it); | ||
return NULL; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://docs.python.org/dev/c-api/tuple.html#c.PyTuple_SET_ITEM and https://docs.python.org/dev/c-api/tuple.html#c.PyTuple_SetItem don't say that the second argument must not be NULL. I suggest to modify the doc to be extra explicit about it.