From b76e79ce344cf60aeeff69c4ca5c96302890ea3c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Mar 2015 01:39:23 +0100 Subject: Issue #23694: Enhance _Py_fopen(), it now raises an exception on error * If fopen() fails, OSError is raised with the original filename object. * The GIL is now released while calling fopen() --- Modules/zipimport.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'Modules/zipimport.c') diff --git a/Modules/zipimport.c b/Modules/zipimport.c index f2cc245b7d..f5ac10beb0 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -875,7 +875,7 @@ read_directory(PyObject *archive) fp = _Py_fopen_obj(archive, "rb"); if (fp == NULL) { - if (!PyErr_Occurred()) + if (PyErr_ExceptionMatches(PyExc_OSError)) PyErr_Format(ZipImportError, "can't open Zip file: %R", archive); return NULL; } @@ -1073,12 +1073,8 @@ get_data(PyObject *archive, PyObject *toc_entry) } fp = _Py_fopen_obj(archive, "rb"); - if (!fp) { - if (!PyErr_Occurred()) - PyErr_Format(PyExc_IOError, - "zipimport: can not open file %U", archive); + if (!fp) return NULL; - } /* Check to make sure the local file header is correct */ if (fseek(fp, file_offset, 0) == -1) { -- cgit v1.2.1 From 02dd357f7b41d8800e99eac56e8cf9a25f765a7c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Mar 2015 13:56:25 +0100 Subject: Issue #19428: Handle PyMarshal_Read*() errors in run_pyc_file() Detect also earlier PyMarshal_Read*() errors in zipimport. --- Modules/zipimport.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Modules/zipimport.c') diff --git a/Modules/zipimport.c b/Modules/zipimport.c index f5ac10beb0..e83214c16c 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -939,6 +939,9 @@ read_directory(PyObject *archive) header_size = name_size + PyMarshal_ReadShortFromFile(fp) + PyMarshal_ReadShortFromFile(fp); + if (PyErr_Occurred()) + goto error; + if (fread(dummy, 1, 8, fp) != 8) /* Skip unused fields, avoid fseek */ goto file_error; file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset; -- cgit v1.2.1 From 8577ee05bb77665efc65873ccd2bfe054db6d98d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 20 Mar 2015 10:52:25 +0100 Subject: Issue #23696: Chain ZipImportError to the OSError --- Modules/zipimport.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Modules/zipimport.c') diff --git a/Modules/zipimport.c b/Modules/zipimport.c index e83214c16c..38dc0c4290 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -875,8 +875,12 @@ read_directory(PyObject *archive) fp = _Py_fopen_obj(archive, "rb"); if (fp == NULL) { - if (PyErr_ExceptionMatches(PyExc_OSError)) + if (PyErr_ExceptionMatches(PyExc_OSError)) { + PyObject *exc, *val, *tb; + PyErr_Fetch(&exc, &val, &tb); PyErr_Format(ZipImportError, "can't open Zip file: %R", archive); + _PyErr_ChainExceptions(exc, val, tb); + } return NULL; } -- cgit v1.2.1 From b09b34b211300f68cc98f6b882f7d2e2f4a76f10 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Mon, 13 Apr 2015 14:21:02 -0400 Subject: Issue #23731: Implement PEP 488. The concept of .pyo files no longer exists. Now .pyc files have an optional `opt-` tag which specifies if any extra optimizations beyond the peepholer were applied. --- Modules/zipimport.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'Modules/zipimport.c') diff --git a/Modules/zipimport.c b/Modules/zipimport.c index 38dc0c4290..06abb312b3 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -20,15 +20,13 @@ _Py_IDENTIFIER(replace); /* zip_searchorder defines how we search for a module in the Zip archive: we first search for a package __init__, then for - non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries + non-package .pyc, and .py entries. The .pyc entries are swapped by initzipimport() if we run in optimized mode. Also, '/' is replaced by SEP there. */ static struct st_zip_searchorder zip_searchorder[] = { {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE}, - {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE}, {"/__init__.py", IS_PACKAGE | IS_SOURCE}, {".pyc", IS_BYTECODE}, - {".pyo", IS_BYTECODE}, {".py", IS_SOURCE}, {"", 0} }; @@ -1318,7 +1316,7 @@ parse_dostime(int dostime, int dosdate) return mktime(&stm); } -/* Given a path to a .pyc or .pyo file in the archive, return the +/* Given a path to a .pyc file in the archive, return the modification time of the matching .py file, or 0 if no source is available. */ static time_t @@ -1481,17 +1479,6 @@ PyInit_zipimport(void) /* Correct directory separator */ zip_searchorder[0].suffix[0] = SEP; zip_searchorder[1].suffix[0] = SEP; - zip_searchorder[2].suffix[0] = SEP; - if (Py_OptimizeFlag) { - /* Reverse *.pyc and *.pyo */ - struct st_zip_searchorder tmp; - tmp = zip_searchorder[0]; - zip_searchorder[0] = zip_searchorder[1]; - zip_searchorder[1] = tmp; - tmp = zip_searchorder[3]; - zip_searchorder[3] = zip_searchorder[4]; - zip_searchorder[4] = tmp; - } mod = PyModule_Create(&zipimportmodule); if (mod == NULL) -- cgit v1.2.1 From 585a1eed45faea53f836b1db2ac211d7f14b44c8 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 24 Dec 2015 10:35:59 +0200 Subject: Issue #20440: Massive replacing unsafe attribute setting code with special macro Py_SETREF. --- Modules/zipimport.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Modules/zipimport.c') diff --git a/Modules/zipimport.c b/Modules/zipimport.c index 06abb312b3..7220faf08d 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -155,8 +155,7 @@ zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds) tmp = PyUnicode_FromFormat("%U%c", self->prefix, SEP); if (tmp == NULL) goto error; - Py_DECREF(self->prefix); - self->prefix = tmp; + Py_SETREF(self->prefix, tmp); } } else -- cgit v1.2.1 From 319014ea8dee7a0ee17ebd54341cdde503e1c97f Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Fri, 15 Jan 2016 11:22:19 -0800 Subject: Issue #17633: Improve support for namespace packages with zipimport. Previously zipimport mistakenly limited namespace support to only the top-level of the zipfile when it should have supported an arbitrary depth. Thanks to Phil Connel for the bug report and initial patch and Mike Romberg for the final patch. --- Modules/zipimport.c | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) (limited to 'Modules/zipimport.c') diff --git a/Modules/zipimport.c b/Modules/zipimport.c index 7220faf08d..b978f269c6 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -324,17 +324,14 @@ get_module_info(ZipImporter *self, PyObject *fullname) } typedef enum { - FL_ERROR, - FL_NOT_FOUND, - FL_MODULE_FOUND, - FL_NS_FOUND + FL_ERROR = -1, /* error */ + FL_NOT_FOUND, /* no loader or namespace portions found */ + FL_MODULE_FOUND, /* module/package found */ + FL_NS_FOUND /* namespace portion found: */ + /* *namespace_portion will point to the name */ } find_loader_result; -/* The guts of "find_loader" and "find_module". Return values: - -1: error - 0: no loader or namespace portions found - 1: module/package found - 2: namespace portion found: *namespace_portion will point to the name +/* The guts of "find_loader" and "find_module". */ static find_loader_result find_loader(ZipImporter *self, PyObject *fullname, PyObject **namespace_portion) @@ -349,21 +346,34 @@ find_loader(ZipImporter *self, PyObject *fullname, PyObject **namespace_portion) if (mi == MI_NOT_FOUND) { /* Not a module or regular package. See if this is a directory, and therefore possibly a portion of a namespace package. */ - int is_dir = check_is_directory(self, self->prefix, fullname); + find_loader_result result = FL_NOT_FOUND; + PyObject *subname; + int is_dir; + + /* We're only interested in the last path component of fullname; + earlier components are recorded in self->prefix. */ + subname = get_subname(fullname); + if (subname == NULL) { + return FL_ERROR; + } + + is_dir = check_is_directory(self, self->prefix, subname); if (is_dir < 0) - return -1; - if (is_dir) { + result = FL_ERROR; + else if (is_dir) { /* This is possibly a portion of a namespace package. Return the string representing its path, without a trailing separator. */ *namespace_portion = PyUnicode_FromFormat("%U%c%U%U", self->archive, SEP, - self->prefix, fullname); + self->prefix, subname); if (*namespace_portion == NULL) - return FL_ERROR; - return FL_NS_FOUND; + result = FL_ERROR; + else + result = FL_NS_FOUND; } - return FL_NOT_FOUND; + Py_DECREF(subname); + return result; } /* This is a module or package. */ return FL_MODULE_FOUND; @@ -397,6 +407,9 @@ zipimporter_find_module(PyObject *obj, PyObject *args) case FL_MODULE_FOUND: result = (PyObject *)self; break; + default: + PyErr_BadInternalCall(); + return NULL; } Py_INCREF(result); return result; @@ -433,6 +446,9 @@ zipimporter_find_loader(PyObject *obj, PyObject *args) result = Py_BuildValue("O[O]", Py_None, namespace_portion); Py_DECREF(namespace_portion); return result; + default: + PyErr_BadInternalCall(); + return NULL; } return result; } -- cgit v1.2.1