Skip to content

Commit 95701bd

Browse files
committed
Issue python#19512: Add PyRun_InteractiveOneObject() function
Only decode the filename once. PyRun_InteractiveOneObject() uses an identifier for "<string>" string, so the byte string is only decoded once.
1 parent 4ee41c5 commit 95701bd

File tree

2 files changed

+86
-29
lines changed

2 files changed

+86
-29
lines changed

Include/pythonrun.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ PyAPI_FUNC(int) PyRun_InteractiveOneFlags(
6363
FILE *fp,
6464
const char *filename, /* decoded from the filesystem encoding */
6565
PyCompilerFlags *flags);
66+
PyAPI_FUNC(int) PyRun_InteractiveOneObject(
67+
FILE *fp,
68+
PyObject *filename,
69+
PyCompilerFlags *flags);
6670
PyAPI_FUNC(int) PyRun_InteractiveLoopFlags(
6771
FILE *fp,
6872
const char *filename, /* decoded from the filesystem encoding */

Python/pythonrun.c

Lines changed: 82 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ static int initfsencoding(PyInterpreterState *interp);
7373
static void initsite(void);
7474
static int initstdio(void);
7575
static void flush_io(void);
76-
static PyObject *run_mod(mod_ty, const char *, PyObject *, PyObject *,
76+
static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *,
7777
PyCompilerFlags *, PyArena *);
7878
static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
7979
PyCompilerFlags *);
@@ -1265,12 +1265,18 @@ PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
12651265
}
12661266

12671267
int
1268-
PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
1268+
PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *flags)
12691269
{
1270-
PyObject *v;
1271-
int ret;
1270+
PyObject *filename, *v;
1271+
int ret, err;
12721272
PyCompilerFlags local_flags;
12731273

1274+
filename = PyUnicode_DecodeFSDefault(filename_str);
1275+
if (filename == NULL) {
1276+
PyErr_Print();
1277+
return -1;
1278+
}
1279+
12741280
if (flags == NULL) {
12751281
flags = &local_flags;
12761282
local_flags.cf_flags = 0;
@@ -1285,16 +1291,21 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flag
12851291
PySys_SetObject("ps2", v = PyUnicode_FromString("... "));
12861292
Py_XDECREF(v);
12871293
}
1294+
err = -1;
12881295
for (;;) {
1289-
ret = PyRun_InteractiveOneFlags(fp, filename, flags);
1296+
ret = PyRun_InteractiveOneObject(fp, filename, flags);
12901297
PRINT_TOTAL_REFS();
1291-
if (ret == E_EOF)
1292-
return 0;
1298+
if (ret == E_EOF) {
1299+
err = 0;
1300+
break;
1301+
}
12931302
/*
12941303
if (ret == E_NOMEM)
1295-
return -1;
1304+
break;
12961305
*/
12971306
}
1307+
Py_DECREF(filename);
1308+
return err;
12981309
}
12991310

13001311
/* compute parser flags based on compiler flags */
@@ -1322,14 +1333,21 @@ static int PARSER_FLAGS(PyCompilerFlags *flags)
13221333
#endif
13231334

13241335
int
1325-
PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
1336+
PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
13261337
{
1327-
PyObject *m, *d, *v, *w, *oenc = NULL;
1338+
PyObject *m, *d, *v, *w, *oenc = NULL, *mod_name;
13281339
mod_ty mod;
13291340
PyArena *arena;
13301341
char *ps1 = "", *ps2 = "", *enc = NULL;
13311342
int errcode = 0;
13321343
_Py_IDENTIFIER(encoding);
1344+
_Py_IDENTIFIER(__main__);
1345+
1346+
mod_name = _PyUnicode_FromId(&PyId___main__); /* borrowed */
1347+
if (mod_name == NULL) {
1348+
PyErr_Print();
1349+
return -1;
1350+
}
13331351

13341352
if (fp == stdin) {
13351353
/* Fetch encoding from sys.stdin if possible. */
@@ -1375,9 +1393,9 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags
13751393
Py_XDECREF(oenc);
13761394
return -1;
13771395
}
1378-
mod = PyParser_ASTFromFile(fp, filename, enc,
1379-
Py_single_input, ps1, ps2,
1380-
flags, &errcode, arena);
1396+
mod = PyParser_ASTFromFileObject(fp, filename, enc,
1397+
Py_single_input, ps1, ps2,
1398+
flags, &errcode, arena);
13811399
Py_XDECREF(v);
13821400
Py_XDECREF(w);
13831401
Py_XDECREF(oenc);
@@ -1390,7 +1408,7 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags
13901408
PyErr_Print();
13911409
return -1;
13921410
}
1393-
m = PyImport_AddModule("__main__");
1411+
m = PyImport_AddModuleObject(mod_name);
13941412
if (m == NULL) {
13951413
PyArena_Free(arena);
13961414
return -1;
@@ -1407,6 +1425,23 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags
14071425
return 0;
14081426
}
14091427

1428+
int
1429+
PyRun_InteractiveOneFlags(FILE *fp, const char *filename_str, PyCompilerFlags *flags)
1430+
{
1431+
PyObject *filename;
1432+
int res;
1433+
1434+
filename = PyUnicode_DecodeFSDefault(filename_str);
1435+
if (filename == NULL) {
1436+
PyErr_Print();
1437+
return -1;
1438+
}
1439+
res = PyRun_InteractiveOneObject(fp, filename, flags);
1440+
Py_DECREF(filename);
1441+
return res;
1442+
}
1443+
1444+
14101445
/* Check whether a file maybe a pyc file: Look at the extension,
14111446
the file type, and, if we may close it, at the first few bytes. */
14121447

@@ -2010,37 +2045,55 @@ PyRun_StringFlags(const char *str, int start, PyObject *globals,
20102045
{
20112046
PyObject *ret = NULL;
20122047
mod_ty mod;
2013-
PyArena *arena = PyArena_New();
2048+
PyArena *arena;
2049+
_Py_static_string(PyId_string, "<string>");
2050+
PyObject *filename;
2051+
2052+
filename = _PyUnicode_FromId(&PyId_string); /* borrowed */
2053+
if (filename == NULL)
2054+
return NULL;
2055+
2056+
arena = PyArena_New();
20142057
if (arena == NULL)
20152058
return NULL;
20162059

2017-
mod = PyParser_ASTFromString(str, "<string>", start, flags, arena);
2060+
mod = PyParser_ASTFromStringObject(str, filename, start, flags, arena);
20182061
if (mod != NULL)
2019-
ret = run_mod(mod, "<string>", globals, locals, flags, arena);
2062+
ret = run_mod(mod, filename, globals, locals, flags, arena);
20202063
PyArena_Free(arena);
20212064
return ret;
20222065
}
20232066

20242067
PyObject *
2025-
PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals,
2068+
PyRun_FileExFlags(FILE *fp, const char *filename_str, int start, PyObject *globals,
20262069
PyObject *locals, int closeit, PyCompilerFlags *flags)
20272070
{
2028-
PyObject *ret;
2071+
PyObject *ret = NULL;
20292072
mod_ty mod;
2030-
PyArena *arena = PyArena_New();
2073+
PyArena *arena = NULL;
2074+
PyObject *filename;
2075+
2076+
filename = PyUnicode_DecodeFSDefault(filename_str);
2077+
if (filename == NULL)
2078+
goto exit;
2079+
2080+
arena = PyArena_New();
20312081
if (arena == NULL)
2032-
return NULL;
2082+
goto exit;
20332083

2034-
mod = PyParser_ASTFromFile(fp, filename, NULL, start, 0, 0,
2035-
flags, NULL, arena);
2084+
mod = PyParser_ASTFromFileObject(fp, filename, NULL, start, 0, 0,
2085+
flags, NULL, arena);
20362086
if (closeit)
20372087
fclose(fp);
20382088
if (mod == NULL) {
2039-
PyArena_Free(arena);
2040-
return NULL;
2089+
goto exit;
20412090
}
20422091
ret = run_mod(mod, filename, globals, locals, flags, arena);
2043-
PyArena_Free(arena);
2092+
2093+
exit:
2094+
Py_XDECREF(filename);
2095+
if (arena != NULL)
2096+
PyArena_Free(arena);
20442097
return ret;
20452098
}
20462099

@@ -2075,12 +2128,12 @@ flush_io(void)
20752128
}
20762129

20772130
static PyObject *
2078-
run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals,
2079-
PyCompilerFlags *flags, PyArena *arena)
2131+
run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals,
2132+
PyCompilerFlags *flags, PyArena *arena)
20802133
{
20812134
PyCodeObject *co;
20822135
PyObject *v;
2083-
co = PyAST_Compile(mod, filename, flags, arena);
2136+
co = PyAST_CompileObject(mod, filename, flags, -1, arena);
20842137
if (co == NULL)
20852138
return NULL;
20862139
v = PyEval_EvalCode((PyObject*)co, globals, locals);

0 commit comments

Comments
 (0)