GeezerVison is showing github.com — Stackless issue #265: fix __reduce__ / __reduce_ex__ · akruis/cpython@10c8679
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: Stackless/changelog.txt +4Lines changed: 4 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -9,6 +9,10 @@ What's New in Stackless 3.X.X? | 9 | 9 |
| 10 | 10 | *Release date: 20XX-XX-XX* | 11 | 11 |
| | 12 | +- https://github.com/stackless-dev/stackless/issues/265 | | 13 | + Avoid undefined behavior, if Stackless classes implement __reduce__() and | | 14 | + __reduce_ex__() using a single C-function. | | 15 | + | 12 | 16 | - https://github.com/stackless-dev/stackless/issues/265 | 13 | 17 | Fix C-API functions PyChannel_Send(), PyChannel_Send_nr(), | 14 | 18 | PyChannel_Receive(), PyChannel_Receive_nr(), and | |
Collapse file Copy file name to clipboardExpand all lines: Stackless/core/cframeobject.c +14-4Lines changed: 14 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -133,14 +133,19 @@ static PyObject * execute_soft_switchable_func(PyFrameObject *, int, PyObject *) | 133 | 133 | SLP_DEF_INVALID_EXEC(execute_soft_switchable_func) | 134 | 134 |
| 135 | 135 | static PyObject * | 136 | | -cframe_reduce(PyCFrameObject *cf) | | 136 | +cframe_reduce(PyCFrameObject *cf, PyObject *value) | 137 | 137 | { | 138 | 138 | PyObject *res = NULL, *exec_name = NULL; | 139 | 139 | PyObject *params = NULL; | 140 | 140 | int valid = 1; | 141 | 141 | PyObject *obs[3]; | 142 | 142 | long i, n; | 143 | 143 |
| | 144 | + if (value && !PyLong_Check(value)) { | | 145 | + PyErr_SetString(PyExc_TypeError, "__reduce_ex__ argument should be an integer"); | | 146 | + return NULL; | | 147 | + } | | 148 | + | 144 | 149 | if (cf->f_execute == execute_soft_switchable_func) { | 145 | 150 | exec_name = (PyObject *) cf->any2; | 146 | 151 | assert(cf->any2); | @@ -240,7 +245,7 @@ cframe_setstate(PyObject *self, PyObject *args) | 240 | 245 |
| 241 | 246 | static PyMethodDef cframe_methods[] = { | 242 | 247 | {"__reduce__", (PyCFunction)cframe_reduce, METH_NOARGS, NULL}, | 243 | | - {"__reduce_ex__", (PyCFunction)cframe_reduce, METH_VARARGS, NULL}, | | 248 | + {"__reduce_ex__", (PyCFunction)cframe_reduce, METH_O, NULL}, | 244 | 249 | {"__setstate__", (PyCFunction)cframe_setstate, METH_O, NULL}, | 245 | 250 | {NULL, NULL} | 246 | 251 | }; | @@ -386,8 +391,13 @@ slp_cframe_fini(void) | 386 | 391 | */ | 387 | 392 |
| 388 | 393 | static PyObject * | 389 | | -function_declaration_reduce(PyStacklessFunctionDeclarationObject *self) | | 394 | +function_declaration_reduce(PyStacklessFunctionDeclarationObject *self, PyObject *value) | 390 | 395 | { | | 396 | + if (value && !PyLong_Check(value)) { | | 397 | + PyErr_SetString(PyExc_TypeError, "__reduce_ex__ argument should be an integer"); | | 398 | + return NULL; | | 399 | + } | | 400 | + | 391 | 401 | if (self->name == NULL || *self->name == '\0') { | 392 | 402 | PyErr_SetString(PyExc_SystemError, "no function name"); | 393 | 403 | return NULL; | @@ -397,7 +407,7 @@ function_declaration_reduce(PyStacklessFunctionDeclarationObject *self) | 397 | 407 |
| 398 | 408 | static PyMethodDef function_declaration_methods[] = { | 399 | 409 | {"__reduce__", (PyCFunction)function_declaration_reduce, METH_NOARGS, NULL}, | 400 | | - {"__reduce_ex__", (PyCFunction)function_declaration_reduce, METH_VARARGS, NULL}, | | 410 | + {"__reduce_ex__", (PyCFunction)function_declaration_reduce, METH_O, NULL}, | 401 | 411 | {NULL, NULL} | 402 | 412 | }; | 403 | 413 |
| |
Collapse file Copy file name to clipboardExpand all lines: Stackless/module/channelobject.c +7-2Lines changed: 7 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1104,12 +1104,17 @@ PyDoc_STRVAR(channel_reduce__doc__, | 1104 | 1104 | "channel.__reduce__() -- currently does not distinguish threads."); | 1105 | 1105 |
| 1106 | 1106 | static PyObject * | 1107 | | -channel_reduce(PyChannelObject * ch) | | 1107 | +channel_reduce(PyChannelObject * ch, PyObject *value) | 1108 | 1108 | { | 1109 | 1109 | PyObject *tup = NULL, *lis = NULL; | 1110 | 1110 | PyTaskletObject *t; | 1111 | 1111 | int i, n; | 1112 | 1112 |
| | 1113 | + if (value && !PyLong_Check(value)) { | | 1114 | + PyErr_SetString(PyExc_TypeError, "__reduce_ex__ argument should be an integer"); | | 1115 | + return NULL; | | 1116 | + } | | 1117 | + | 1113 | 1118 | lis = PyList_New(0); | 1114 | 1119 | if (lis == NULL) goto err_exit; | 1115 | 1120 | t = ch->head; | @@ -1188,7 +1193,7 @@ channel_methods[] = { | 1188 | 1193 | channel_open__doc__}, | 1189 | 1194 | {"__reduce__", (PCF)channel_reduce, METH_NOARGS, | 1190 | 1195 | channel_reduce__doc__}, | 1191 | | - {"__reduce_ex__", (PCF)channel_reduce, METH_VARARGS, | | 1196 | + {"__reduce_ex__", (PCF)channel_reduce, METH_O, | 1192 | 1197 | channel_reduce__doc__}, | 1193 | 1198 | {"__setstate__", (PCF)channel_setstate, METH_O, | 1194 | 1199 | channel_setstate__doc__}, | |
Collapse file Copy file name to clipboardExpand all lines: Stackless/module/scheduling.c +7-2Lines changed: 7 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -216,10 +216,15 @@ slp_bomb_explode(PyObject *_bomb) | 216 | 216 | } | 217 | 217 |
| 218 | 218 | static PyObject * | 219 | | -bomb_reduce(PyBombObject *bomb) | | 219 | +bomb_reduce(PyBombObject *bomb, PyObject *value) | 220 | 220 | { | 221 | 221 | PyObject *tup; | 222 | 222 |
| | 223 | + if (value && !PyLong_Check(value)) { | | 224 | + PyErr_SetString(PyExc_TypeError, "__reduce_ex__ argument should be an integer"); | | 225 | + return NULL; | | 226 | + } | | 227 | + | 223 | 228 | tup = slp_into_tuple_with_nulls(&bomb->curexc_type, 3); | 224 | 229 | if (tup != NULL) | 225 | 230 | tup = Py_BuildValue("(O()O)", &PyBomb_Type, tup); | @@ -246,7 +251,7 @@ static PyMemberDef bomb_members[] = { | 246 | 251 |
| 247 | 252 | static PyMethodDef bomb_methods[] = { | 248 | 253 | {"__reduce__", (PyCFunction)bomb_reduce, METH_NOARGS}, | 249 | | - {"__reduce_ex__", (PyCFunction)bomb_reduce, METH_VARARGS}, | | 254 | + {"__reduce_ex__", (PyCFunction)bomb_reduce, METH_O}, | 250 | 255 | {"__setstate__", (PyCFunction)bomb_setstate, METH_O}, | 251 | 256 | {NULL, NULL} /* sentinel */ | 252 | 257 | }; | |
Collapse file Copy file name to clipboardExpand all lines: Stackless/module/stacklessmodule.c +7-2Lines changed: 7 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -855,8 +855,13 @@ get_thread_info(PyObject *self, PyObject *args) | 855 | 855 | } | 856 | 856 |
| 857 | 857 | static PyObject * | 858 | | -slpmodule_reduce(PyObject *self) | | 858 | +slpmodule_reduce(PyObject *self, PyObject *value) | 859 | 859 | { | | 860 | + if (value && !PyLong_Check(value)) { | | 861 | + PyErr_SetString(PyExc_TypeError, "__reduce_ex__ argument should be an integer"); | | 862 | + return NULL; | | 863 | + } | | 864 | + | 860 | 865 | return PyUnicode_FromString("_stackless"); | 861 | 866 | } | 862 | 867 |
| @@ -1709,7 +1714,7 @@ static PyMethodDef stackless_methods[] = { | 1709 | 1714 | _get_all_objects__doc__}, | 1710 | 1715 | #endif | 1711 | 1716 | {"__reduce__", (PCF)slpmodule_reduce, METH_NOARGS, NULL}, | 1712 | | - {"__reduce_ex__", (PCF)slpmodule_reduce, METH_VARARGS, NULL}, | | 1717 | + {"__reduce_ex__", (PCF)slpmodule_reduce, METH_O, NULL}, | 1713 | 1718 | {"getdebug", (PCF)slpmodule_getdebug, METH_NOARGS, | 1714 | 1719 | slpmodule_getdebug__doc__}, | 1715 | 1720 | {"getuncollectables", (PCF)slpmodule_getuncollectables, METH_NOARGS, | |
Collapse file Copy file name to clipboardExpand all lines: Stackless/module/taskletobject.c +7-2Lines changed: 7 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -612,14 +612,19 @@ simply the tasklet() call without parameters. | 612 | 612 | */ | 613 | 613 |
| 614 | 614 | static PyObject * | 615 | | -tasklet_reduce(PyTaskletObject * t) | | 615 | +tasklet_reduce(PyTaskletObject * t, PyObject *value) | 616 | 616 | { | 617 | 617 | PyObject *tup = NULL, *lis = NULL; | 618 | 618 | PyFrameObject *f; | 619 | 619 | PyThreadState *ts = t->cstate->tstate; | 620 | 620 | PyObject *exc_type, *exc_value, *exc_traceback, *exc_info; | 621 | 621 | PyObject *context = NULL; | 622 | 622 |
| | 623 | + if (value && !PyLong_Check(value)) { | | 624 | + PyErr_SetString(PyExc_TypeError, "__reduce_ex__ argument should be an integer"); | | 625 | + return NULL; | | 626 | + } | | 627 | + | 623 | 628 | if (ts && t == ts->st.current) | 624 | 629 | RUNTIME_ERROR("You cannot __reduce__ the tasklet which is" | 625 | 630 | " current.", NULL); | @@ -2580,7 +2585,7 @@ static PyMethodDef tasklet_methods[] = { | 2580 | 2585 | tasklet_setup__doc__}, | 2581 | 2586 | {"__reduce__", (PCF)tasklet_reduce, METH_NOARGS, | 2582 | 2587 | tasklet_reduce__doc__}, | 2583 | | - {"__reduce_ex__", (PCF)tasklet_reduce, METH_VARARGS, | | 2588 | + {"__reduce_ex__", (PCF)tasklet_reduce, METH_O, | 2584 | 2589 | tasklet_reduce__doc__}, | 2585 | 2590 | {"__setstate__", (PCF)tasklet_setstate, METH_O, | 2586 | 2591 | tasklet_setstate__doc__}, | |
|