Skip to content

Commit cf30d5c

Browse files
bpo-24618: Add a check in the code constructor. (GH-8283) (GH-8311)
Check that the size of the varnames tuple is enough at least for all arguments. (cherry picked from commit bd47384)
1 parent cc13016 commit cf30d5c

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed reading invalid memory when create the code object with too small
2+
varnames tuple or too large argument counts.

‎Objects/codeobject.c‎

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ PyCode_New(int argcount, int kwonlyargcount,
114114
{
115115
PyCodeObject *co;
116116
unsigned char *cell2arg = NULL;
117-
Py_ssize_t i, n_cellvars;
117+
Py_ssize_t i, n_cellvars, n_varnames, total_args;
118118

119119
/* Check argument types */
120120
if (argcount < 0 || kwonlyargcount < 0 || nlocals < 0 ||
@@ -150,23 +150,42 @@ PyCode_New(int argcount, int kwonlyargcount,
150150
flags &= ~CO_NOFREE;
151151
}
152152

153+
n_varnames = PyTuple_GET_SIZE(varnames);
154+
if (argcount <= n_varnames && kwonlyargcount <= n_varnames) {
155+
/* Never overflows. */
156+
total_args = (Py_ssize_t)argcount + (Py_ssize_t)kwonlyargcount +
157+
((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
158+
}
159+
else {
160+
total_args = n_varnames + 1;
161+
}
162+
if (total_args > n_varnames) {
163+
PyErr_SetString(PyExc_ValueError, "code: varnames is too small");
164+
return NULL;
165+
}
166+
153167
/* Create mapping between cells and arguments if needed. */
154168
if (n_cellvars) {
155-
Py_ssize_t total_args = argcount + kwonlyargcount +
156-
((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
157169
Py_ssize_t alloc_size = sizeof(unsigned char) * n_cellvars;
158170
bool used_cell2arg = false;
159171
cell2arg = PyMem_MALLOC(alloc_size);
160-
if (cell2arg == NULL)
172+
if (cell2arg == NULL) {
173+
PyErr_NoMemory();
161174
return NULL;
175+
}
162176
memset(cell2arg, CO_CELL_NOT_AN_ARG, alloc_size);
163177
/* Find cells which are also arguments. */
164178
for (i = 0; i < n_cellvars; i++) {
165179
Py_ssize_t j;
166180
PyObject *cell = PyTuple_GET_ITEM(cellvars, i);
167181
for (j = 0; j < total_args; j++) {
168182
PyObject *arg = PyTuple_GET_ITEM(varnames, j);
169-
if (!PyUnicode_Compare(cell, arg)) {
183+
int cmp = PyUnicode_Compare(cell, arg);
184+
if (cmp == -1 && PyErr_Occurred()) {
185+
PyMem_FREE(cell2arg);
186+
return NULL;
187+
}
188+
if (cmp == 0) {
170189
cell2arg[i] = j;
171190
used_cell2arg = true;
172191
break;

0 commit comments

Comments
 (0)