Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 93ab55b

Browse filesBrowse files
[3.14] gh-132775: Use _PyFunction_VerifyStateless() and _PyCode_VerifyStateless() (gh-134465)
(cherry picked from commit a66bae8, AKA gh-134439) Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
1 parent 11d77d2 commit 93ab55b
Copy full SHA for 93ab55b

File tree

Expand file treeCollapse file tree

3 files changed

+70
-76
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+70
-76
lines changed

‎Include/internal/pycore_pyerrors.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_pyerrors.h
+2-2Lines 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,

‎Lib/test/test__interpreters.py

Copy file name to clipboardExpand all lines: Lib/test/test__interpreters.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,7 @@ def test_closure(self):
10541054
def script():
10551055
assert spam
10561056

1057-
with self.assertRaises(ValueError):
1057+
with self.assertRaises(TypeError):
10581058
_interpreters.run_func(self.id, script)
10591059

10601060
# XXX This hasn't been fixed yet.
@@ -1065,6 +1065,7 @@ def script():
10651065
with self.assertRaises(ValueError):
10661066
_interpreters.run_func(self.id, script)
10671067

1068+
@unittest.skip("we're not quite there yet")
10681069
def test_args(self):
10691070
with self.subTest('args'):
10701071
def script(a, b=0):

‎Modules/_interpretersmodule.c

Copy file name to clipboardExpand all lines: Modules/_interpretersmodule.c
+66-73Lines changed: 66 additions & 73 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,53 @@ 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;
990-
}
991-
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;
975+
// For now we allow globals, so we can't use
976+
// _PyFunction_VerifyStateless().
977+
PyObject *codeobj = PyFunction_GetCode(arg);
978+
if (_PyCode_VerifyStateless(
979+
tstate, (PyCodeObject *)codeobj, NULL, NULL, NULL) < 0) {
980+
goto chained;
1003981
}
1004-
Py_INCREF(code);
1005-
kind = "func";
982+
code = (PyCodeObject *)Py_NewRef(codeobj);
1006983
}
1007984
else if (PyCode_Check(arg)) {
985+
if (_PyCode_VerifyStateless(
986+
tstate, (PyCodeObject *)arg, NULL, NULL, NULL) < 0) {
987+
goto chained;
988+
}
1008989
code = (PyCodeObject *)Py_NewRef(arg);
1009-
kind = "code object";
1010990
}
1011991
else {
1012992
_PyArg_BadArgument(fname, displayname, expected, arg);
1013993
return NULL;
1014994
}
1015995

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-
1024996
return code;
997+
998+
chained:
999+
cause = _PyErr_GetRaisedException(tstate);
1000+
assert(cause != NULL);
1001+
_PyArg_BadArgument(fname, displayname, expected, arg);
1002+
PyObject *exc = _PyErr_GetRaisedException(tstate);
1003+
PyException_SetCause(exc, cause);
1004+
_PyErr_SetRaisedException(tstate, exc);
1005+
return NULL;
10251006
}
10261007

10271008
static int
@@ -1057,12 +1038,14 @@ _interp_exec(PyObject *self, PyInterpreterState *interp,
10571038
static PyObject *
10581039
interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
10591040
{
1041+
#define FUNCNAME MODULE_NAME_STR ".exec"
1042+
PyThreadState *tstate = _PyThreadState_GET();
10601043
static char *kwlist[] = {"id", "code", "shared", "restrict", NULL};
10611044
PyObject *id, *code;
10621045
PyObject *shared = NULL;
10631046
int restricted = 0;
10641047
if (!PyArg_ParseTupleAndKeywords(args, kwds,
1065-
"OO|O$p:" MODULE_NAME_STR ".exec", kwlist,
1048+
"OO|O$p:" FUNCNAME, kwlist,
10661049
&id, &code, &shared, &restricted))
10671050
{
10681051
return NULL;
@@ -1077,12 +1060,12 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
10771060

10781061
const char *expected = "a string, a function, or a code object";
10791062
if (PyUnicode_Check(code)) {
1080-
code = (PyObject *)convert_script_arg(code, MODULE_NAME_STR ".exec",
1081-
"argument 2", expected);
1063+
code = (PyObject *)convert_script_arg(tstate, code, FUNCNAME,
1064+
"argument 2", expected);
10821065
}
10831066
else {
1084-
code = (PyObject *)convert_code_arg(code, MODULE_NAME_STR ".exec",
1085-
"argument 2", expected);
1067+
code = (PyObject *)convert_code_arg(tstate, code, FUNCNAME,
1068+
"argument 2", expected);
10861069
}
10871070
if (code == NULL) {
10881071
return NULL;
@@ -1096,6 +1079,7 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
10961079
return excinfo;
10971080
}
10981081
Py_RETURN_NONE;
1082+
#undef FUNCNAME
10991083
}
11001084

11011085
PyDoc_STRVAR(exec_doc,
@@ -1118,13 +1102,15 @@ is ignored, including its __globals__ dict.");
11181102
static PyObject *
11191103
interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
11201104
{
1105+
#define FUNCNAME MODULE_NAME_STR ".run_string"
1106+
PyThreadState *tstate = _PyThreadState_GET();
11211107
static char *kwlist[] = {"id", "script", "shared", "restrict", NULL};
11221108
PyObject *id, *script;
11231109
PyObject *shared = NULL;
11241110
int restricted = 0;
11251111
if (!PyArg_ParseTupleAndKeywords(args, kwds,
1126-
"OU|O$p:" MODULE_NAME_STR ".run_string",
1127-
kwlist, &id, &script, &shared, &restricted))
1112+
"OU|O$p:" FUNCNAME, kwlist,
1113+
&id, &script, &shared, &restricted))
11281114
{
11291115
return NULL;
11301116
}
@@ -1136,7 +1122,7 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
11361122
return NULL;
11371123
}
11381124

1139-
script = (PyObject *)convert_script_arg(script, MODULE_NAME_STR ".run_string",
1125+
script = (PyObject *)convert_script_arg(tstate, script, FUNCNAME,
11401126
"argument 2", "a string");
11411127
if (script == NULL) {
11421128
return NULL;
@@ -1150,6 +1136,7 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
11501136
return excinfo;
11511137
}
11521138
Py_RETURN_NONE;
1139+
#undef FUNCNAME
11531140
}
11541141

11551142
PyDoc_STRVAR(run_string_doc,
@@ -1162,13 +1149,15 @@ Execute the provided string in the identified interpreter.\n\
11621149
static PyObject *
11631150
interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
11641151
{
1152+
#define FUNCNAME MODULE_NAME_STR ".run_func"
1153+
PyThreadState *tstate = _PyThreadState_GET();
11651154
static char *kwlist[] = {"id", "func", "shared", "restrict", NULL};
11661155
PyObject *id, *func;
11671156
PyObject *shared = NULL;
11681157
int restricted = 0;
11691158
if (!PyArg_ParseTupleAndKeywords(args, kwds,
1170-
"OO|O$p:" MODULE_NAME_STR ".run_func",
1171-
kwlist, &id, &func, &shared, &restricted))
1159+
"OO|O$p:" FUNCNAME, kwlist,
1160+
&id, &func, &shared, &restricted))
11721161
{
11731162
return NULL;
11741163
}
@@ -1180,7 +1169,7 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
11801169
return NULL;
11811170
}
11821171

1183-
PyCodeObject *code = convert_code_arg(func, MODULE_NAME_STR ".exec",
1172+
PyCodeObject *code = convert_code_arg(tstate, func, FUNCNAME,
11841173
"argument 2",
11851174
"a function or a code object");
11861175
if (code == NULL) {
@@ -1195,6 +1184,7 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
11951184
return excinfo;
11961185
}
11971186
Py_RETURN_NONE;
1187+
#undef FUNCNAME
11981188
}
11991189

12001190
PyDoc_STRVAR(run_func_doc,
@@ -1209,14 +1199,16 @@ are not supported. Methods and other callables are not supported either.\n\
12091199
static PyObject *
12101200
interp_call(PyObject *self, PyObject *args, PyObject *kwds)
12111201
{
1202+
#define FUNCNAME MODULE_NAME_STR ".call"
1203+
PyThreadState *tstate = _PyThreadState_GET();
12121204
static char *kwlist[] = {"id", "callable", "args", "kwargs",
12131205
"restrict", NULL};
12141206
PyObject *id, *callable;
12151207
PyObject *args_obj = NULL;
12161208
PyObject *kwargs_obj = NULL;
12171209
int restricted = 0;
12181210
if (!PyArg_ParseTupleAndKeywords(args, kwds,
1219-
"OO|OO$p:" MODULE_NAME_STR ".call", kwlist,
1211+
"OO|OO$p:" FUNCNAME, kwlist,
12201212
&id, &callable, &args_obj, &kwargs_obj,
12211213
&restricted))
12221214
{
@@ -1231,15 +1223,15 @@ interp_call(PyObject *self, PyObject *args, PyObject *kwds)
12311223
}
12321224

12331225
if (args_obj != NULL) {
1234-
PyErr_SetString(PyExc_ValueError, "got unexpected args");
1226+
_PyErr_SetString(tstate, PyExc_ValueError, "got unexpected args");
12351227
return NULL;
12361228
}
12371229
if (kwargs_obj != NULL) {
1238-
PyErr_SetString(PyExc_ValueError, "got unexpected kwargs");
1230+
_PyErr_SetString(tstate, PyExc_ValueError, "got unexpected kwargs");
12391231
return NULL;
12401232
}
12411233

1242-
PyObject *code = (PyObject *)convert_code_arg(callable, MODULE_NAME_STR ".call",
1234+
PyObject *code = (PyObject *)convert_code_arg(tstate, callable, FUNCNAME,
12431235
"argument 2", "a function");
12441236
if (code == NULL) {
12451237
return NULL;
@@ -1253,6 +1245,7 @@ interp_call(PyObject *self, PyObject *args, PyObject *kwds)
12531245
return excinfo;
12541246
}
12551247
Py_RETURN_NONE;
1248+
#undef FUNCNAME
12561249
}
12571250

12581251
PyDoc_STRVAR(call_doc,

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.