bpo-32381: Fix PyRun_SimpleFileExFlags() encoding (GH-23642)
Fix encoding name when running a ".pyc" file on Windows: PyRun_SimpleFileExFlags() now uses the correct encoding to decode the filename. * Add pyrun_file() subfunction. * Add pyrun_simple_file() subfunction. * PyRun_SimpleFileExFlags() now calls _Py_fopen_obj() rather than _Py_fopen().
This commit is contained in:
parent
233fddfe39
commit
b6d98c10ff
|
@ -0,0 +1,3 @@
|
|||
Fix encoding name when running a ``.pyc`` file on Windows:
|
||||
:c:func:`PyRun_SimpleFileExFlags()` now uses the correct encoding to decode
|
||||
the filename.
|
|
@ -59,9 +59,13 @@ extern "C" {
|
|||
static void flush_io(void);
|
||||
static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *,
|
||||
PyCompilerFlags *, PyArena *);
|
||||
static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
|
||||
static PyObject *run_pyc_file(FILE *, PyObject *, PyObject *,
|
||||
PyCompilerFlags *);
|
||||
static int PyRun_InteractiveOneObjectEx(FILE *, PyObject *, PyCompilerFlags *);
|
||||
static PyObject* pyrun_file(FILE *fp, PyObject *filename, int start,
|
||||
PyObject *globals, PyObject *locals, int closeit,
|
||||
PyCompilerFlags *flags);
|
||||
|
||||
|
||||
/* Parse input from a file and execute it */
|
||||
int
|
||||
|
@ -269,14 +273,24 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename_str, PyCompilerFlags *f
|
|||
the file type, and, if we may close it, at the first few bytes. */
|
||||
|
||||
static int
|
||||
maybe_pyc_file(FILE *fp, const char* filename, const char* ext, int closeit)
|
||||
maybe_pyc_file(FILE *fp, PyObject *filename, int closeit)
|
||||
{
|
||||
if (strcmp(ext, ".pyc") == 0)
|
||||
PyObject *ext = PyUnicode_FromString(".pyc");
|
||||
if (ext == NULL) {
|
||||
return -1;
|
||||
}
|
||||
Py_ssize_t endswith = PyUnicode_Tailmatch(filename, ext, 0, PY_SSIZE_T_MAX, +1);
|
||||
Py_DECREF(ext);
|
||||
if (endswith) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Only look into the file if we are allowed to close it, since
|
||||
it then should also be seekable. */
|
||||
if (closeit) {
|
||||
if (!closeit) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read only two bytes of the magic. If the file was opened in
|
||||
text mode, the bytes 3 and 4 of the magic (\r\n) might not
|
||||
be read as they are on disk. */
|
||||
|
@ -302,49 +316,46 @@ maybe_pyc_file(FILE *fp, const char* filename, const char* ext, int closeit)
|
|||
}
|
||||
return ispyc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
set_main_loader(PyObject *d, const char *filename, const char *loader_name)
|
||||
set_main_loader(PyObject *d, PyObject *filename, const char *loader_name)
|
||||
{
|
||||
PyObject *filename_obj, *bootstrap, *loader_type = NULL, *loader;
|
||||
int result = 0;
|
||||
|
||||
filename_obj = PyUnicode_DecodeFSDefault(filename);
|
||||
if (filename_obj == NULL)
|
||||
return -1;
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
bootstrap = PyObject_GetAttrString(interp->importlib,
|
||||
PyObject *bootstrap = PyObject_GetAttrString(interp->importlib,
|
||||
"_bootstrap_external");
|
||||
if (bootstrap != NULL) {
|
||||
loader_type = PyObject_GetAttrString(bootstrap, loader_name);
|
||||
Py_DECREF(bootstrap);
|
||||
}
|
||||
if (loader_type == NULL) {
|
||||
Py_DECREF(filename_obj);
|
||||
if (bootstrap == NULL) {
|
||||
return -1;
|
||||
}
|
||||
loader = PyObject_CallFunction(loader_type, "sN", "__main__", filename_obj);
|
||||
|
||||
PyObject *loader_type = PyObject_GetAttrString(bootstrap, loader_name);
|
||||
Py_DECREF(bootstrap);
|
||||
if (loader_type == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *loader = PyObject_CallFunction(loader_type,
|
||||
"sO", "__main__", filename);
|
||||
Py_DECREF(loader_type);
|
||||
if (loader == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(d, "__loader__", loader) < 0) {
|
||||
result = -1;
|
||||
Py_DECREF(loader);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(loader);
|
||||
return result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
|
||||
|
||||
static int
|
||||
pyrun_simple_file(FILE *fp, PyObject *filename, int closeit,
|
||||
PyCompilerFlags *flags)
|
||||
{
|
||||
PyObject *m, *d, *v;
|
||||
const char *ext;
|
||||
int set_file_name = 0, ret = -1;
|
||||
size_t len;
|
||||
|
||||
m = PyImport_AddModule("__main__");
|
||||
if (m == NULL)
|
||||
|
@ -355,29 +366,29 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
|
|||
if (PyErr_Occurred()) {
|
||||
goto done;
|
||||
}
|
||||
PyObject *f;
|
||||
f = PyUnicode_DecodeFSDefault(filename);
|
||||
if (f == NULL)
|
||||
goto done;
|
||||
if (PyDict_SetItemString(d, "__file__", f) < 0) {
|
||||
Py_DECREF(f);
|
||||
if (PyDict_SetItemString(d, "__file__", filename) < 0) {
|
||||
goto done;
|
||||
}
|
||||
if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) {
|
||||
Py_DECREF(f);
|
||||
goto done;
|
||||
}
|
||||
set_file_name = 1;
|
||||
Py_DECREF(f);
|
||||
}
|
||||
len = strlen(filename);
|
||||
ext = filename + len - (len > 4 ? 4 : 0);
|
||||
if (maybe_pyc_file(fp, filename, ext, closeit)) {
|
||||
|
||||
int pyc = maybe_pyc_file(fp, filename, closeit);
|
||||
if (pyc < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (pyc) {
|
||||
FILE *pyc_fp;
|
||||
/* Try to run a pyc file. First, re-open in binary */
|
||||
if (closeit)
|
||||
if (closeit) {
|
||||
fclose(fp);
|
||||
if ((pyc_fp = _Py_fopen(filename, "rb")) == NULL) {
|
||||
}
|
||||
|
||||
pyc_fp = _Py_fopen_obj(filename, "rb");
|
||||
if (pyc_fp == NULL) {
|
||||
fprintf(stderr, "python: Can't reopen .pyc file\n");
|
||||
goto done;
|
||||
}
|
||||
|
@ -388,16 +399,16 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
|
|||
fclose(pyc_fp);
|
||||
goto done;
|
||||
}
|
||||
v = run_pyc_file(pyc_fp, filename, d, d, flags);
|
||||
v = run_pyc_file(pyc_fp, d, d, flags);
|
||||
} else {
|
||||
/* When running from stdin, leave __main__.__loader__ alone */
|
||||
if (strcmp(filename, "<stdin>") != 0 &&
|
||||
if (PyUnicode_CompareWithASCIIString(filename, "<stdin>") != 0 &&
|
||||
set_main_loader(d, filename, "SourceFileLoader") < 0) {
|
||||
fprintf(stderr, "python: failed to set __main__.__loader__\n");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d,
|
||||
v = pyrun_file(fp, filename, Py_file_input, d, d,
|
||||
closeit, flags);
|
||||
}
|
||||
flush_io();
|
||||
|
@ -421,6 +432,21 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
|
||||
PyCompilerFlags *flags)
|
||||
{
|
||||
PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);
|
||||
if (filename_obj == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int res = pyrun_simple_file(fp, filename_obj, closeit, flags);
|
||||
Py_DECREF(filename_obj);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags)
|
||||
{
|
||||
|
@ -1039,40 +1065,54 @@ PyRun_StringFlags(const char *str, int start, PyObject *globals,
|
|||
return ret;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyRun_FileExFlags(FILE *fp, const char *filename_str, int start, PyObject *globals,
|
||||
|
||||
static PyObject *
|
||||
pyrun_file(FILE *fp, PyObject *filename, int start, PyObject *globals,
|
||||
PyObject *locals, int closeit, PyCompilerFlags *flags)
|
||||
{
|
||||
PyObject *ret = NULL;
|
||||
PyArena *arena = PyArena_New();
|
||||
if (arena == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mod_ty mod;
|
||||
PyArena *arena = NULL;
|
||||
PyObject *filename;
|
||||
|
||||
filename = PyUnicode_DecodeFSDefault(filename_str);
|
||||
if (filename == NULL)
|
||||
goto exit;
|
||||
|
||||
arena = PyArena_New();
|
||||
if (arena == NULL)
|
||||
goto exit;
|
||||
|
||||
mod = PyParser_ASTFromFileObject(fp, filename, NULL, start, NULL, NULL,
|
||||
flags, NULL, arena);
|
||||
|
||||
if (closeit)
|
||||
if (closeit) {
|
||||
fclose(fp);
|
||||
if (mod == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
ret = run_mod(mod, filename, globals, locals, flags, arena);
|
||||
|
||||
exit:
|
||||
Py_XDECREF(filename);
|
||||
if (arena != NULL)
|
||||
PyObject *ret;
|
||||
if (mod != NULL) {
|
||||
ret = run_mod(mod, filename, globals, locals, flags, arena);
|
||||
}
|
||||
else {
|
||||
ret = NULL;
|
||||
}
|
||||
PyArena_Free(arena);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals,
|
||||
PyObject *locals, int closeit, PyCompilerFlags *flags)
|
||||
{
|
||||
PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);
|
||||
if (filename_obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *res = pyrun_file(fp, filename_obj, start, globals,
|
||||
locals, closeit, flags);
|
||||
Py_DECREF(filename_obj);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
flush_io(void)
|
||||
{
|
||||
|
@ -1155,8 +1195,8 @@ run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals,
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
run_pyc_file(FILE *fp, const char *filename, PyObject *globals,
|
||||
PyObject *locals, PyCompilerFlags *flags)
|
||||
run_pyc_file(FILE *fp, PyObject *globals, PyObject *locals,
|
||||
PyCompilerFlags *flags)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
PyCodeObject *co;
|
||||
|
|
Loading…
Reference in New Issue