mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-32381: Fix PyRun_SimpleFileExFlags() encoding (GH-23642) (GH-23692)
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().
(cherry picked from commit b6d98c10ff)
			
			
This commit is contained in:
		
							parent
							
								
									170dec3598
								
							
						
					
					
						commit
						f0e42ae03c
					
				
					 2 changed files with 138 additions and 95 deletions
				
			
		|  | @ -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. | ||||||
|  | @ -64,11 +64,15 @@ extern Py_EXPORTED_SYMBOL grammar _PyParser_Grammar; /* From graminit.c */ | ||||||
| static void flush_io(void); | static void flush_io(void); | ||||||
| static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *, | static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *, | ||||||
|                           PyCompilerFlags *, PyArena *); |                           PyCompilerFlags *, PyArena *); | ||||||
| static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, | static PyObject *run_pyc_file(FILE *, PyObject *, PyObject *, | ||||||
|                               PyCompilerFlags *); |                               PyCompilerFlags *); | ||||||
| static void err_input(perrdetail *); | static void err_input(perrdetail *); | ||||||
| static void err_free(perrdetail *); | static void err_free(perrdetail *); | ||||||
| static int PyRun_InteractiveOneObjectEx(FILE *, 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 */ | /* Parse input from a file and execute it */ | ||||||
| int | int | ||||||
|  | @ -310,14 +314,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. */ |    the file type, and, if we may close it, at the first few bytes. */ | ||||||
| 
 | 
 | ||||||
| static int | 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; |         return 1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Only look into the file if we are allowed to close it, since
 |     /* Only look into the file if we are allowed to close it, since
 | ||||||
|        it then should also be seekable. */ |        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
 |     /* 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 |        text mode, the bytes 3 and 4 of the magic (\r\n) might not | ||||||
|        be read as they are on disk. */ |        be read as they are on disk. */ | ||||||
|  | @ -343,49 +357,46 @@ maybe_pyc_file(FILE *fp, const char* filename, const char* ext, int closeit) | ||||||
|     } |     } | ||||||
|     return ispyc; |     return ispyc; | ||||||
| } | } | ||||||
|     return 0; | 
 | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| static int | 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(); |     PyInterpreterState *interp = _PyInterpreterState_GET(); | ||||||
|     bootstrap = PyObject_GetAttrString(interp->importlib, |     PyObject *bootstrap = PyObject_GetAttrString(interp->importlib, | ||||||
|                                                  "_bootstrap_external"); |                                                  "_bootstrap_external"); | ||||||
|     if (bootstrap != NULL) { |     if (bootstrap == NULL) { | ||||||
|         loader_type = PyObject_GetAttrString(bootstrap, loader_name); |  | ||||||
|         Py_DECREF(bootstrap); |  | ||||||
|     } |  | ||||||
|     if (loader_type == NULL) { |  | ||||||
|         Py_DECREF(filename_obj); |  | ||||||
|         return -1; |         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); |     Py_DECREF(loader_type); | ||||||
|     if (loader == NULL) { |     if (loader == NULL) { | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     if (PyDict_SetItemString(d, "__loader__", loader) < 0) { |     if (PyDict_SetItemString(d, "__loader__", loader) < 0) { | ||||||
|         result = -1; |         Py_DECREF(loader); | ||||||
|  |         return -1; | ||||||
|     } |     } | ||||||
|     Py_DECREF(loader); |     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) |                   PyCompilerFlags *flags) | ||||||
| { | { | ||||||
|     PyObject *m, *d, *v; |     PyObject *m, *d, *v; | ||||||
|     const char *ext; |  | ||||||
|     int set_file_name = 0, ret = -1; |     int set_file_name = 0, ret = -1; | ||||||
|     size_t len; |  | ||||||
| 
 | 
 | ||||||
|     m = PyImport_AddModule("__main__"); |     m = PyImport_AddModule("__main__"); | ||||||
|     if (m == NULL) |     if (m == NULL) | ||||||
|  | @ -393,29 +404,29 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, | ||||||
|     Py_INCREF(m); |     Py_INCREF(m); | ||||||
|     d = PyModule_GetDict(m); |     d = PyModule_GetDict(m); | ||||||
|     if (PyDict_GetItemString(d, "__file__") == NULL) { |     if (PyDict_GetItemString(d, "__file__") == NULL) { | ||||||
|         PyObject *f; |         if (PyDict_SetItemString(d, "__file__", filename) < 0) { | ||||||
|         f = PyUnicode_DecodeFSDefault(filename); |  | ||||||
|         if (f == NULL) |  | ||||||
|             goto done; |  | ||||||
|         if (PyDict_SetItemString(d, "__file__", f) < 0) { |  | ||||||
|             Py_DECREF(f); |  | ||||||
|             goto done; |             goto done; | ||||||
|         } |         } | ||||||
|         if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) { |         if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) { | ||||||
|             Py_DECREF(f); |  | ||||||
|             goto done; |             goto done; | ||||||
|         } |         } | ||||||
|         set_file_name = 1; |         set_file_name = 1; | ||||||
|         Py_DECREF(f); |  | ||||||
|     } |     } | ||||||
|     len = strlen(filename); | 
 | ||||||
|     ext = filename + len - (len > 4 ? 4 : 0); |     int pyc = maybe_pyc_file(fp, filename, closeit); | ||||||
|     if (maybe_pyc_file(fp, filename, ext, closeit)) { |     if (pyc < 0) { | ||||||
|  |         goto done; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (pyc) { | ||||||
|         FILE *pyc_fp; |         FILE *pyc_fp; | ||||||
|         /* Try to run a pyc file. First, re-open in binary */ |         /* Try to run a pyc file. First, re-open in binary */ | ||||||
|         if (closeit) |         if (closeit) { | ||||||
|             fclose(fp); |             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"); |             fprintf(stderr, "python: Can't reopen .pyc file\n"); | ||||||
|             goto done; |             goto done; | ||||||
|         } |         } | ||||||
|  | @ -426,16 +437,16 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, | ||||||
|             fclose(pyc_fp); |             fclose(pyc_fp); | ||||||
|             goto done; |             goto done; | ||||||
|         } |         } | ||||||
|         v = run_pyc_file(pyc_fp, filename, d, d, flags); |         v = run_pyc_file(pyc_fp, d, d, flags); | ||||||
|     } else { |     } else { | ||||||
|         /* When running from stdin, leave __main__.__loader__ alone */ |         /* 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) { |             set_main_loader(d, filename, "SourceFileLoader") < 0) { | ||||||
|             fprintf(stderr, "python: failed to set __main__.__loader__\n"); |             fprintf(stderr, "python: failed to set __main__.__loader__\n"); | ||||||
|             ret = -1; |             ret = -1; | ||||||
|             goto done; |             goto done; | ||||||
|         } |         } | ||||||
|         v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d, |         v = pyrun_file(fp, filename, Py_file_input, d, d, | ||||||
|                        closeit, flags); |                        closeit, flags); | ||||||
|     } |     } | ||||||
|     flush_io(); |     flush_io(); | ||||||
|  | @ -459,6 +470,21 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, | ||||||
|     return ret; |     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 | int | ||||||
| PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags) | PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags) | ||||||
| { | { | ||||||
|  | @ -1081,24 +1107,18 @@ PyRun_StringFlags(const char *str, int start, PyObject *globals, | ||||||
|     return ret; |     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 *locals, int closeit, PyCompilerFlags *flags) | ||||||
| { | { | ||||||
|     PyObject *ret = NULL; |     PyArena *arena = PyArena_New(); | ||||||
|  |     if (arena == NULL) { | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     mod_ty mod; |     mod_ty mod; | ||||||
|     PyArena *arena = NULL; |  | ||||||
|     PyObject *filename; |  | ||||||
|     int use_peg = _PyInterpreterState_GET()->config._use_peg_parser; |     int use_peg = _PyInterpreterState_GET()->config._use_peg_parser; | ||||||
| 
 |  | ||||||
|     filename = PyUnicode_DecodeFSDefault(filename_str); |  | ||||||
|     if (filename == NULL) |  | ||||||
|         goto exit; |  | ||||||
| 
 |  | ||||||
|     arena = PyArena_New(); |  | ||||||
|     if (arena == NULL) |  | ||||||
|         goto exit; |  | ||||||
| 
 |  | ||||||
|     if (use_peg) { |     if (use_peg) { | ||||||
|         mod = PyPegen_ASTFromFileObject(fp, filename, start, NULL, NULL, NULL, |         mod = PyPegen_ASTFromFileObject(fp, filename, start, NULL, NULL, NULL, | ||||||
|                                         flags, NULL, arena); |                                         flags, NULL, arena); | ||||||
|  | @ -1108,20 +1128,40 @@ PyRun_FileExFlags(FILE *fp, const char *filename_str, int start, PyObject *globa | ||||||
|                                          flags, NULL, arena); |                                          flags, NULL, arena); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (closeit) |     if (closeit) { | ||||||
|         fclose(fp); |         fclose(fp); | ||||||
|     if (mod == NULL) { |  | ||||||
|         goto exit; |  | ||||||
|     } |     } | ||||||
|     ret = run_mod(mod, filename, globals, locals, flags, arena); |  | ||||||
| 
 | 
 | ||||||
| exit: |     PyObject *ret; | ||||||
|     Py_XDECREF(filename); |     if (mod != NULL) { | ||||||
|     if (arena != NULL) |         ret = run_mod(mod, filename, globals, locals, flags, arena); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         ret = NULL; | ||||||
|  |     } | ||||||
|     PyArena_Free(arena); |     PyArena_Free(arena); | ||||||
|  | 
 | ||||||
|     return ret; |     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 | static void | ||||||
| flush_io(void) | flush_io(void) | ||||||
| { | { | ||||||
|  | @ -1202,8 +1242,8 @@ run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyObject * | static PyObject * | ||||||
| run_pyc_file(FILE *fp, const char *filename, PyObject *globals, | run_pyc_file(FILE *fp, PyObject *globals, PyObject *locals, | ||||||
|              PyObject *locals, PyCompilerFlags *flags) |              PyCompilerFlags *flags) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     PyThreadState *tstate = _PyThreadState_GET(); | ||||||
|     PyCodeObject *co; |     PyCodeObject *co; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner