Skip to content

Commit b73166e

Browse files
authored
Stackless issue python#265: Fix (invalid) function cast warnings with gcc 8
* fix PyChannel_Send_M The implementation was buggy. This affects only users of the C-API, that call PyChannel_Send() and PyChannel_Send_nr() for calls from outside of the interpreter (with no main-tasklet). * fix PyChannel_Receive_M and tasklet_new If called from outside of the interpreter the behavior was undefined. (Calling a C-function with wrong number of arguments). * fix __reduce__ / __reduce_ex__ Avoid undefined behavior, if Stackless classes implement __reduce__() and __reduce_ex__() using a single C-function. __reduce_ex__ now checks the type of its argument. * fix the signature of tp_clear functions Return type is 'int', not 'void'. * add missing arguments to C-function definitions Most (getter)-functions, (setter)-functions and (PyCFunction)-functions with flag METH_NOARGS lack an unused last argument, "void *" for (getter) and (setter), "PyObject *" for (PyCFunction)-functions. This commit adds these arguments. * Fix invalid function cast warnings Fix invalid function cast warnings with gcc 8 for method conventions different from METH_NOARGS, METH_O and METH_VARARGS excluding Argument Clinic generated code.
1 parent 88271d3 commit b73166e

File tree

10 files changed

+181
-114
lines changed

10 files changed

+181
-114
lines changed

Include/internal/pycore_stackless.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ PyObject* slp_context_run_callback(PyFrameObject *f, int exc, PyObject *result);
780780
(ts->st.runflags & PY_WATCHDOG_IGNORE_NESTING))
781781

782782
/* Interpreter shutdown and thread state access */
783-
PyObject * slp_getthreads(PyObject *self);
783+
PyObject * slp_getthreads(PyObject *self, PyObject *unused);
784784
void slp_head_lock(void);
785785
void slp_head_unlock(void);
786786
#define SLP_HEAD_LOCK() slp_head_lock()

Modules/_pickle.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4689,7 +4689,7 @@ Pickler_set_memo(PicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored))
46894689

46904690
#ifdef STACKLESS
46914691
static PyObject *
4692-
Pickler_get_module_dict_ids(PicklerObject *p)
4692+
Pickler_get_module_dict_ids(PicklerObject *p, void *closure)
46934693
{
46944694
if (p->module_dict_ids == NULL)
46954695
PyErr_SetString(PyExc_AttributeError, "module_dict_ids");
@@ -4699,7 +4699,7 @@ Pickler_get_module_dict_ids(PicklerObject *p)
46994699
}
47004700

47014701
static int
4702-
Pickler_set_module_dict_ids(PicklerObject *p, PyObject *v)
4702+
Pickler_set_module_dict_ids(PicklerObject *p, PyObject *v, void *closure)
47034703
{
47044704
if (v == NULL) {
47054705
PyErr_SetString(PyExc_TypeError,

Stackless/changelog.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,26 @@ What's New in Stackless 3.X.X?
99

1010
*Release date: 20XX-XX-XX*
1111

12+
- https://github.com/stackless-dev/stackless/issues/265
13+
Fix invalid function cast warnings with gcc 8 for method conventions
14+
different from METH_NOARGS, METH_O and METH_VARARGS excluding Argument Clinic
15+
generated code.
16+
17+
- https://github.com/stackless-dev/stackless/issues/265
18+
Most (getter)-functions, (setter)-functions and (PyCFunction)-functions with
19+
flag METH_NOARGS used to lack an unused last argument, "void *" for (getter)
20+
and (setter), "PyObject *" for (PyCFunction)-functions.
21+
22+
- https://github.com/stackless-dev/stackless/issues/265
23+
Avoid undefined behavior, if Stackless classes implement __reduce__() and
24+
__reduce_ex__() using a single C-function.
25+
26+
- https://github.com/stackless-dev/stackless/issues/265
27+
Fix C-API functions PyChannel_Send(), PyChannel_Send_nr(),
28+
PyChannel_Receive(), PyChannel_Receive_nr(), and
29+
PyObject_Call(&PyTasklet_Type, PyObject *args, PyObject *kwargs) if called
30+
from outside of the interpreter (with no main-tasklet).
31+
1232
- https://github.com/stackless-dev/stackless/issues/264
1333
Implement bpo-35134 for Stackless: move header Include/slp_tstate.h to
1434
Include/cpython/slp_tstate.h.

Stackless/core/cframeobject.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ cframe_traverse(PyCFrameObject *cf, visitproc visit, void *arg)
6666

6767
/* clearing a cframe while the object still exists */
6868

69-
static void
69+
static int
7070
cframe_clear(PyCFrameObject *cf)
7171
{
7272
/* The Python C-API documentation recomends to use Py_CLEAR() to release
@@ -86,6 +86,7 @@ cframe_clear(PyCFrameObject *cf)
8686
Py_XDECREF(tmp_ob1);
8787
Py_XDECREF(tmp_ob2);
8888
Py_XDECREF(tmp_ob3);
89+
return 0;
8990
}
9091

9192

@@ -133,14 +134,19 @@ static PyObject * execute_soft_switchable_func(PyFrameObject *, int, PyObject *)
133134
SLP_DEF_INVALID_EXEC(execute_soft_switchable_func)
134135

135136
static PyObject *
136-
cframe_reduce(PyCFrameObject *cf)
137+
cframe_reduce(PyCFrameObject *cf, PyObject *value)
137138
{
138139
PyObject *res = NULL, *exec_name = NULL;
139140
PyObject *params = NULL;
140141
int valid = 1;
141142
PyObject *obs[3];
142143
long i, n;
143144

145+
if (value && !PyLong_Check(value)) {
146+
PyErr_SetString(PyExc_TypeError, "__reduce_ex__ argument should be an integer");
147+
return NULL;
148+
}
149+
144150
if (cf->f_execute == execute_soft_switchable_func) {
145151
exec_name = (PyObject *) cf->any2;
146152
assert(cf->any2);
@@ -240,7 +246,7 @@ cframe_setstate(PyObject *self, PyObject *args)
240246

241247
static PyMethodDef cframe_methods[] = {
242248
{"__reduce__", (PyCFunction)cframe_reduce, METH_NOARGS, NULL},
243-
{"__reduce_ex__", (PyCFunction)cframe_reduce, METH_VARARGS, NULL},
249+
{"__reduce_ex__", (PyCFunction)cframe_reduce, METH_O, NULL},
244250
{"__setstate__", (PyCFunction)cframe_setstate, METH_O, NULL},
245251
{NULL, NULL}
246252
};
@@ -386,8 +392,13 @@ slp_cframe_fini(void)
386392
*/
387393

388394
static PyObject *
389-
function_declaration_reduce(PyStacklessFunctionDeclarationObject *self)
395+
function_declaration_reduce(PyStacklessFunctionDeclarationObject *self, PyObject *value)
390396
{
397+
if (value && !PyLong_Check(value)) {
398+
PyErr_SetString(PyExc_TypeError, "__reduce_ex__ argument should be an integer");
399+
return NULL;
400+
}
401+
391402
if (self->name == NULL || *self->name == '\0') {
392403
PyErr_SetString(PyExc_SystemError, "no function name");
393404
return NULL;
@@ -397,7 +408,7 @@ function_declaration_reduce(PyStacklessFunctionDeclarationObject *self)
397408

398409
static PyMethodDef function_declaration_methods[] = {
399410
{"__reduce__", (PyCFunction)function_declaration_reduce, METH_NOARGS, NULL},
400-
{"__reduce_ex__", (PyCFunction)function_declaration_reduce, METH_VARARGS, NULL},
411+
{"__reduce_ex__", (PyCFunction)function_declaration_reduce, METH_O, NULL},
401412
{NULL, NULL}
402413
};
403414

Stackless/module/_teststackless.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,11 +494,11 @@ static PyObject* test_PyEval_EvalFrameEx(PyObject *self, PyObject *args, PyObjec
494494
static PyMethodDef _teststackless_methods[] = {
495495
{"softswitchablefunc", _teststackless_softswitchabledemo, METH_VARARGS | METH_STACKLESS,
496496
_teststackless_softswitchabledemo_doc},
497-
{ "test_cframe", (PyCFunction) test_cframe, METH_VARARGS | METH_KEYWORDS,
497+
{ "test_cframe", (PyCFunction)(void(*)(void))test_cframe, METH_VARARGS | METH_KEYWORDS,
498498
test_cframe__doc__ },
499499
{ "test_cstate", (PyCFunction) test_cstate, METH_O,
500500
test_cstate__doc__ },
501-
{ "test_PyEval_EvalFrameEx", (PyCFunction) test_PyEval_EvalFrameEx, METH_VARARGS | METH_KEYWORDS,
501+
{ "test_PyEval_EvalFrameEx", (PyCFunction)(void(*)(void))test_PyEval_EvalFrameEx, METH_VARARGS | METH_KEYWORDS,
502502
test_PyEval_EvalFrameEx__doc__ },
503503
{NULL, NULL} /* sentinel */
504504
};

Stackless/module/channelobject.c

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ channel_traverse(PyChannelObject *ch, visitproc visit, void *arg)
5656
return 0;
5757
}
5858

59-
static void
59+
static int
6060
channel_clear(PyObject *ob)
6161
{
6262
PyChannelObject *ch = (PyChannelObject *) ob;
@@ -74,6 +74,7 @@ channel_clear(PyObject *ob)
7474
ob = (PyObject *) slp_channel_remove(ch, NULL, NULL, NULL);
7575
Py_DECREF(ob);
7676
}
77+
return 0;
7778
}
7879

7980
static void
@@ -195,7 +196,7 @@ channel_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
195196
}
196197

197198
static PyObject *
198-
channel_get_queue(PyChannelObject *self)
199+
channel_get_queue(PyChannelObject *self, void *closure)
199200
{
200201
PyObject *ret = (PyObject*) self->head;
201202

@@ -208,11 +209,11 @@ channel_get_queue(PyChannelObject *self)
208209
PyObject *
209210
PyChannel_GetQueue(PyChannelObject *self)
210211
{
211-
return channel_get_queue(self);
212+
return channel_get_queue(self, NULL);
212213
}
213214

214215
static PyObject *
215-
channel_get_closing(PyChannelObject *self)
216+
channel_get_closing(PyChannelObject *self, void *closure)
216217
{
217218
return PyBool_FromLong(self->flags.closing);
218219
}
@@ -224,7 +225,7 @@ PyChannel_GetClosing(PyChannelObject *self)
224225
}
225226

226227
static PyObject *
227-
channel_get_closed(PyChannelObject *self)
228+
channel_get_closed(PyChannelObject *self, void *closure)
228229
{
229230
return PyBool_FromLong(self->flags.closing && self->balance == 0);
230231
}
@@ -237,13 +238,13 @@ PyChannel_GetClosed(PyChannelObject *self)
237238

238239

239240
static PyObject *
240-
channel_get_preference(PyChannelObject *self)
241+
channel_get_preference(PyChannelObject *self, void *closure)
241242
{
242243
return PyLong_FromLong(self->flags.preference);
243244
}
244245

245246
static int
246-
channel_set_preference(PyChannelObject *self, PyObject *value)
247+
channel_set_preference(PyChannelObject *self, PyObject *value, void *closure)
247248
{
248249
int val;
249250

@@ -267,13 +268,13 @@ PyChannel_SetPreference(PyChannelObject *self, int val)
267268
}
268269

269270
static PyObject *
270-
channel_get_schedule_all(PyChannelObject *self)
271+
channel_get_schedule_all(PyChannelObject *self, void *closure)
271272
{
272273
return PyLong_FromLong(self->flags.schedule_all);
273274
}
274275

275276
static int
276-
channel_set_schedule_all(PyChannelObject *self, PyObject *value)
277+
channel_set_schedule_all(PyChannelObject *self, PyObject *value, void *closure)
277278
{
278279
if (!PyLong_Check(value))
279280
TYPE_ERROR("preference must be set to a bool or integer", -1);
@@ -425,10 +426,13 @@ the sender will be blocked. Otherwise, the receiver will\n\
425426
be activated immediately, and the sender is put at the end of\n\
426427
the runnables list.");
427428

429+
static PyObject *
430+
impl_channel_send(PyChannelObject *self, PyObject *arg);
431+
428432
static PyObject *
429433
PyChannel_Send_M(PyChannelObject *self, PyObject *arg)
430434
{
431-
PyMethodDef def = {"send", (PyCFunction)PyChannel_Send, METH_O};
435+
PyMethodDef def = {"send", (PyCFunction)impl_channel_send, METH_O};
432436
return PyStackless_CallCMethod_Main(&def, (PyObject *) self, "O", arg);
433437
}
434438

@@ -770,10 +774,16 @@ continue immediately, and the sender is put at the end of\n\
770774
the runnables list.\n\
771775
The above policy can be changed by setting channel flags.");
772776

777+
static PyObject *
778+
PyChannel_Receive_cfunc(PyChannelObject *self, PyObject *unused)
779+
{
780+
return PyChannel_Receive(self);
781+
}
782+
773783
static PyObject *
774784
PyChannel_Receive_M(PyChannelObject *self)
775785
{
776-
PyMethodDef def = {"receive", (PyCFunction)PyChannel_Receive, METH_NOARGS};
786+
PyMethodDef def = {"receive", (PyCFunction)PyChannel_Receive_cfunc, METH_NOARGS};
777787
return PyStackless_CallCMethod_Main(&def, (PyObject *) self, NULL);
778788
}
779789

@@ -809,7 +819,7 @@ PyChannel_Receive(PyChannelObject *self)
809819
}
810820

811821
static PyObject *
812-
channel_receive(PyObject *self)
822+
channel_receive(PyObject *self, PyObject *unused)
813823
{
814824
return impl_channel_receive((PyChannelObject*)self);
815825
}
@@ -1059,7 +1069,7 @@ If the channel is not empty, the flag 'closing' becomes true.\n\
10591069
If the channel is empty, the flag 'closed' becomes true.");
10601070

10611071
static PyObject *
1062-
channel_close(PyChannelObject *self)
1072+
channel_close(PyChannelObject *self, PyObject *unused)
10631073
{
10641074
self->flags.closing = 1;
10651075

@@ -1077,7 +1087,7 @@ PyDoc_STRVAR(channel_open__doc__,
10771087
"channel.open() -- reopen a channel. See channel.close.");
10781088

10791089
static PyObject *
1080-
channel_open(PyChannelObject *self)
1090+
channel_open(PyChannelObject *self, PyObject *unused)
10811091
{
10821092
self->flags.closing = 0;
10831093

@@ -1095,12 +1105,17 @@ PyDoc_STRVAR(channel_reduce__doc__,
10951105
"channel.__reduce__() -- currently does not distinguish threads.");
10961106

10971107
static PyObject *
1098-
channel_reduce(PyChannelObject * ch)
1108+
channel_reduce(PyChannelObject * ch, PyObject *value)
10991109
{
11001110
PyObject *tup = NULL, *lis = NULL;
11011111
PyTaskletObject *t;
11021112
int i, n;
11031113

1114+
if (value && !PyLong_Check(value)) {
1115+
PyErr_SetString(PyExc_TypeError, "__reduce_ex__ argument should be an integer");
1116+
return NULL;
1117+
}
1118+
11041119
lis = PyList_New(0);
11051120
if (lis == NULL) goto err_exit;
11061121
t = ch->head;
@@ -1179,7 +1194,7 @@ channel_methods[] = {
11791194
channel_open__doc__},
11801195
{"__reduce__", (PCF)channel_reduce, METH_NOARGS,
11811196
channel_reduce__doc__},
1182-
{"__reduce_ex__", (PCF)channel_reduce, METH_VARARGS,
1197+
{"__reduce_ex__", (PCF)channel_reduce, METH_O,
11831198
channel_reduce__doc__},
11841199
{"__setstate__", (PCF)channel_setstate, METH_O,
11851200
channel_setstate__doc__},

Stackless/module/scheduling.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,13 @@ bomb_traverse(PyBombObject *bomb, visitproc visit, void *arg)
4242
return 0;
4343
}
4444

45-
static void
45+
static int
4646
bomb_clear(PyBombObject *bomb)
4747
{
4848
Py_CLEAR(bomb->curexc_type);
4949
Py_CLEAR(bomb->curexc_value);
5050
Py_CLEAR(bomb->curexc_traceback);
51+
return 0;
5152
}
5253

5354
PyBombObject *
@@ -216,10 +217,15 @@ slp_bomb_explode(PyObject *_bomb)
216217
}
217218

218219
static PyObject *
219-
bomb_reduce(PyBombObject *bomb)
220+
bomb_reduce(PyBombObject *bomb, PyObject *value)
220221
{
221222
PyObject *tup;
222223

224+
if (value && !PyLong_Check(value)) {
225+
PyErr_SetString(PyExc_TypeError, "__reduce_ex__ argument should be an integer");
226+
return NULL;
227+
}
228+
223229
tup = slp_into_tuple_with_nulls(&bomb->curexc_type, 3);
224230
if (tup != NULL)
225231
tup = Py_BuildValue("(O()O)", &PyBomb_Type, tup);
@@ -246,7 +252,7 @@ static PyMemberDef bomb_members[] = {
246252

247253
static PyMethodDef bomb_methods[] = {
248254
{"__reduce__", (PyCFunction)bomb_reduce, METH_NOARGS},
249-
{"__reduce_ex__", (PyCFunction)bomb_reduce, METH_VARARGS},
255+
{"__reduce_ex__", (PyCFunction)bomb_reduce, METH_O},
250256
{"__setstate__", (PyCFunction)bomb_setstate, METH_O},
251257
{NULL, NULL} /* sentinel */
252258
};

0 commit comments

Comments
 (0)