Skip to content

Commit e9bbebe

Browse files
Use _PyFunction_VerifyStateless() and _PyCode_VerifyStateless().
1 parent 04308b9 commit e9bbebe

File tree

2 files changed

+63
-73
lines changed

2 files changed

+63
-73
lines changed

Include/internal/pycore_pyerrors.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,13 @@ extern void _PyErr_Fetch(
9494
PyObject **value,
9595
PyObject **traceback);
9696

97-
extern PyObject* _PyErr_GetRaisedException(PyThreadState *tstate);
97+
PyAPI_FUNC(PyObject*) _PyErr_GetRaisedException(PyThreadState *tstate);
9898

9999
PyAPI_FUNC(int) _PyErr_ExceptionMatches(
100100
PyThreadState *tstate,
101101
PyObject *exc);
102102

103-
extern void _PyErr_SetRaisedException(PyThreadState *tstate, PyObject *exc);
103+
PyAPI_FUNC(void) _PyErr_SetRaisedException(PyThreadState *tstate, PyObject *exc);
104104

105105
extern void _PyErr_Restore(
106106
PyThreadState *tstate,

Modules/_interpretersmodule.c

Lines changed: 61 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "Python.h"
99
#include "pycore_code.h" // _PyCode_HAS_EXECUTORS()
1010
#include "pycore_crossinterp.h" // _PyXIData_t
11+
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
12+
#include "pycore_function.h" // _PyFunction_VerifyStateless()
1113
#include "pycore_interp.h" // _PyInterpreterState_IDIncref()
1214
#include "pycore_modsupport.h" // _PyArg_BadArgument()
1315
#include "pycore_namespace.h" // _PyNamespace_New()
@@ -374,34 +376,17 @@ check_code_str(PyUnicodeObject *text)
374376
return NULL;
375377
}
376378

377-
static const char *
378-
check_code_object(PyCodeObject *code)
379+
#ifndef NDEBUG
380+
static int
381+
code_has_args(PyCodeObject *code)
379382
{
380383
assert(code != NULL);
381-
if (code->co_argcount > 0
384+
return (code->co_argcount > 0
382385
|| code->co_posonlyargcount > 0
383386
|| code->co_kwonlyargcount > 0
384-
|| code->co_flags & (CO_VARARGS | CO_VARKEYWORDS))
385-
{
386-
return "arguments not supported";
387-
}
388-
if (code->co_ncellvars > 0) {
389-
return "closures not supported";
390-
}
391-
// We trust that no code objects under co_consts have unbound cell vars.
392-
393-
if (_PyCode_HAS_EXECUTORS(code) || _PyCode_HAS_INSTRUMENTATION(code)) {
394-
return "only basic functions are supported";
395-
}
396-
if (code->_co_monitoring != NULL) {
397-
return "only basic functions are supported";
398-
}
399-
if (code->co_extra != NULL) {
400-
return "only basic functions are supported";
401-
}
402-
403-
return NULL;
387+
|| code->co_flags & (CO_VARARGS | CO_VARKEYWORDS));
404388
}
389+
#endif
405390

406391
#define RUN_TEXT 1
407392
#define RUN_CODE 2
@@ -429,8 +414,10 @@ get_code_str(PyObject *arg, Py_ssize_t *len_p, PyObject **bytes_p, int *flags_p)
429414
flags = RUN_TEXT;
430415
}
431416
else {
432-
assert(PyCode_Check(arg)
433-
&& (check_code_object((PyCodeObject *)arg) == NULL));
417+
assert(PyCode_Check(arg));
418+
assert(_PyCode_VerifyStateless(
419+
PyThreadState_Get(), (PyCodeObject *)arg, NULL, NULL, NULL) == 0);
420+
assert(!code_has_args((PyCodeObject *)arg));
434421
flags = RUN_CODE;
435422

436423
// Serialize the code object.
@@ -949,7 +936,8 @@ Bind the given attributes in the interpreter's __main__ module.");
949936

950937

951938
static PyUnicodeObject *
952-
convert_script_arg(PyObject *arg, const char *fname, const char *displayname,
939+
convert_script_arg(PyThreadState *tstate,
940+
PyObject *arg, const char *fname, const char *displayname,
953941
const char *expected)
954942
{
955943
PyUnicodeObject *str = NULL;
@@ -968,60 +956,50 @@ convert_script_arg(PyObject *arg, const char *fname, const char *displayname,
968956
const char *err = check_code_str(str);
969957
if (err != NULL) {
970958
Py_DECREF(str);
971-
PyErr_Format(PyExc_ValueError,
972-
"%.200s(): bad script text (%s)", fname, err);
959+
_PyErr_Format(tstate, PyExc_ValueError,
960+
"%.200s(): bad script text (%s)", fname, err);
973961
return NULL;
974962
}
975963

976964
return str;
977965
}
978966

979967
static PyCodeObject *
980-
convert_code_arg(PyObject *arg, const char *fname, const char *displayname,
968+
convert_code_arg(PyThreadState *tstate,
969+
PyObject *arg, const char *fname, const char *displayname,
981970
const char *expected)
982971
{
983-
const char *kind = NULL;
972+
PyObject *cause;
984973
PyCodeObject *code = NULL;
985974
if (PyFunction_Check(arg)) {
986-
if (PyFunction_GetClosure(arg) != NULL) {
987-
PyErr_Format(PyExc_ValueError,
988-
"%.200s(): closures not supported", fname);
989-
return NULL;
975+
if (_PyFunction_VerifyStateless(tstate, arg) < 0) {
976+
goto chained;
990977
}
991978
code = (PyCodeObject *)PyFunction_GetCode(arg);
992-
if (code == NULL) {
993-
if (PyErr_Occurred()) {
994-
// This chains.
995-
PyErr_Format(PyExc_ValueError,
996-
"%.200s(): bad func", fname);
997-
}
998-
else {
999-
PyErr_Format(PyExc_ValueError,
1000-
"%.200s(): func.__code__ missing", fname);
1001-
}
1002-
return NULL;
1003-
}
1004979
Py_INCREF(code);
1005-
kind = "func";
1006980
}
1007981
else if (PyCode_Check(arg)) {
982+
if (_PyCode_VerifyStateless(
983+
tstate, (PyCodeObject *)arg, NULL, NULL, NULL) < 0) {
984+
goto chained;
985+
}
1008986
code = (PyCodeObject *)Py_NewRef(arg);
1009-
kind = "code object";
1010987
}
1011988
else {
1012989
_PyArg_BadArgument(fname, displayname, expected, arg);
1013990
return NULL;
1014991
}
1015992

1016-
const char *err = check_code_object(code);
1017-
if (err != NULL) {
1018-
Py_DECREF(code);
1019-
PyErr_Format(PyExc_ValueError,
1020-
"%.200s(): bad %s (%s)", fname, kind, err);
1021-
return NULL;
1022-
}
1023-
1024993
return code;
994+
995+
chained:
996+
cause = _PyErr_GetRaisedException(tstate);
997+
assert(cause != NULL);
998+
_PyArg_BadArgument(fname, displayname, expected, arg);
999+
PyObject *exc = _PyErr_GetRaisedException(tstate);
1000+
PyException_SetCause(exc, cause);
1001+
_PyErr_SetRaisedException(tstate, exc);
1002+
return NULL;
10251003
}
10261004

10271005
static int
@@ -1057,12 +1035,14 @@ _interp_exec(PyObject *self, PyInterpreterState *interp,
10571035
static PyObject *
10581036
interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
10591037
{
1038+
#define FUNCNAME MODULE_NAME_STR ".exec"
1039+
PyThreadState *tstate = _PyThreadState_GET();
10601040
static char *kwlist[] = {"id", "code", "shared", "restrict", NULL};
10611041
PyObject *id, *code;
10621042
PyObject *shared = NULL;
10631043
int restricted = 0;
10641044
if (!PyArg_ParseTupleAndKeywords(args, kwds,
1065-
"OO|O$p:" MODULE_NAME_STR ".exec", kwlist,
1045+
"OO|O$p:" FUNCNAME, kwlist,
10661046
&id, &code, &shared, &restricted))
10671047
{
10681048
return NULL;
@@ -1077,12 +1057,12 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
10771057

10781058
const char *expected = "a string, a function, or a code object";
10791059
if (PyUnicode_Check(code)) {
1080-
code = (PyObject *)convert_script_arg(code, MODULE_NAME_STR ".exec",
1081-
"argument 2", expected);
1060+
code = (PyObject *)convert_script_arg(tstate, code, FUNCNAME,
1061+
"argument 2", expected);
10821062
}
10831063
else {
1084-
code = (PyObject *)convert_code_arg(code, MODULE_NAME_STR ".exec",
1085-
"argument 2", expected);
1064+
code = (PyObject *)convert_code_arg(tstate, code, FUNCNAME,
1065+
"argument 2", expected);
10861066
}
10871067
if (code == NULL) {
10881068
return NULL;
@@ -1096,6 +1076,7 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
10961076
return excinfo;
10971077
}
10981078
Py_RETURN_NONE;
1079+
#undef FUNCNAME
10991080
}
11001081

11011082
PyDoc_STRVAR(exec_doc,
@@ -1118,13 +1099,15 @@ is ignored, including its __globals__ dict.");
11181099
static PyObject *
11191100
interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
11201101
{
1102+
#define FUNCNAME MODULE_NAME_STR ".run_string"
1103+
PyThreadState *tstate = _PyThreadState_GET();
11211104
static char *kwlist[] = {"id", "script", "shared", "restrict", NULL};
11221105
PyObject *id, *script;
11231106
PyObject *shared = NULL;
11241107
int restricted = 0;
11251108
if (!PyArg_ParseTupleAndKeywords(args, kwds,
1126-
"OU|O$p:" MODULE_NAME_STR ".run_string",
1127-
kwlist, &id, &script, &shared, &restricted))
1109+
"OU|O$p:" FUNCNAME, kwlist,
1110+
&id, &script, &shared, &restricted))
11281111
{
11291112
return NULL;
11301113
}
@@ -1136,7 +1119,7 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
11361119
return NULL;
11371120
}
11381121

1139-
script = (PyObject *)convert_script_arg(script, MODULE_NAME_STR ".run_string",
1122+
script = (PyObject *)convert_script_arg(tstate, script, FUNCNAME,
11401123
"argument 2", "a string");
11411124
if (script == NULL) {
11421125
return NULL;
@@ -1150,6 +1133,7 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
11501133
return excinfo;
11511134
}
11521135
Py_RETURN_NONE;
1136+
#undef FUNCNAME
11531137
}
11541138

11551139
PyDoc_STRVAR(run_string_doc,
@@ -1162,13 +1146,15 @@ Execute the provided string in the identified interpreter.\n\
11621146
static PyObject *
11631147
interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
11641148
{
1149+
#define FUNCNAME MODULE_NAME_STR ".run_func"
1150+
PyThreadState *tstate = _PyThreadState_GET();
11651151
static char *kwlist[] = {"id", "func", "shared", "restrict", NULL};
11661152
PyObject *id, *func;
11671153
PyObject *shared = NULL;
11681154
int restricted = 0;
11691155
if (!PyArg_ParseTupleAndKeywords(args, kwds,
1170-
"OO|O$p:" MODULE_NAME_STR ".run_func",
1171-
kwlist, &id, &func, &shared, &restricted))
1156+
"OO|O$p:" FUNCNAME, kwlist,
1157+
&id, &func, &shared, &restricted))
11721158
{
11731159
return NULL;
11741160
}
@@ -1180,7 +1166,7 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
11801166
return NULL;
11811167
}
11821168

1183-
PyCodeObject *code = convert_code_arg(func, MODULE_NAME_STR ".exec",
1169+
PyCodeObject *code = convert_code_arg(tstate, func, FUNCNAME,
11841170
"argument 2",
11851171
"a function or a code object");
11861172
if (code == NULL) {
@@ -1195,6 +1181,7 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
11951181
return excinfo;
11961182
}
11971183
Py_RETURN_NONE;
1184+
#undef FUNCNAME
11981185
}
11991186

12001187
PyDoc_STRVAR(run_func_doc,
@@ -1209,14 +1196,16 @@ are not supported. Methods and other callables are not supported either.\n\
12091196
static PyObject *
12101197
interp_call(PyObject *self, PyObject *args, PyObject *kwds)
12111198
{
1199+
#define FUNCNAME MODULE_NAME_STR ".call"
1200+
PyThreadState *tstate = _PyThreadState_GET();
12121201
static char *kwlist[] = {"id", "callable", "args", "kwargs",
12131202
"restrict", NULL};
12141203
PyObject *id, *callable;
12151204
PyObject *args_obj = NULL;
12161205
PyObject *kwargs_obj = NULL;
12171206
int restricted = 0;
12181207
if (!PyArg_ParseTupleAndKeywords(args, kwds,
1219-
"OO|OO$p:" MODULE_NAME_STR ".call", kwlist,
1208+
"OO|OO$p:" FUNCNAME, kwlist,
12201209
&id, &callable, &args_obj, &kwargs_obj,
12211210
&restricted))
12221211
{
@@ -1231,15 +1220,15 @@ interp_call(PyObject *self, PyObject *args, PyObject *kwds)
12311220
}
12321221

12331222
if (args_obj != NULL) {
1234-
PyErr_SetString(PyExc_ValueError, "got unexpected args");
1223+
_PyErr_SetString(tstate, PyExc_ValueError, "got unexpected args");
12351224
return NULL;
12361225
}
12371226
if (kwargs_obj != NULL) {
1238-
PyErr_SetString(PyExc_ValueError, "got unexpected kwargs");
1227+
_PyErr_SetString(tstate, PyExc_ValueError, "got unexpected kwargs");
12391228
return NULL;
12401229
}
12411230

1242-
PyObject *code = (PyObject *)convert_code_arg(callable, MODULE_NAME_STR ".call",
1231+
PyObject *code = (PyObject *)convert_code_arg(tstate, callable, FUNCNAME,
12431232
"argument 2", "a function");
12441233
if (code == NULL) {
12451234
return NULL;
@@ -1253,6 +1242,7 @@ interp_call(PyObject *self, PyObject *args, PyObject *kwds)
12531242
return excinfo;
12541243
}
12551244
Py_RETURN_NONE;
1245+
#undef FUNCNAME
12561246
}
12571247

12581248
PyDoc_STRVAR(call_doc,

0 commit comments

Comments
 (0)