Commit eb43736d authored by Benjamin Peterson's avatar Benjamin Peterson

backout 2807a5f011e4 for causing #20621

parent c20b4d87
...@@ -46,27 +46,6 @@ pyc_file = imp.cache_from_source(TESTMOD + '.py') ...@@ -46,27 +46,6 @@ pyc_file = imp.cache_from_source(TESTMOD + '.py')
pyc_ext = ('.pyc' if __debug__ else '.pyo') pyc_ext = ('.pyc' if __debug__ else '.pyo')
def _write_zip_package(zipname, files,
data_to_prepend=b"", compression=ZIP_STORED):
z = ZipFile(zipname, "w")
try:
for name, (mtime, data) in files.items():
zinfo = ZipInfo(name, time.localtime(mtime))
zinfo.compress_type = compression
z.writestr(zinfo, data)
finally:
z.close()
if data_to_prepend:
# Prepend data to the start of the zipfile
with open(zipname, "rb") as f:
zip_data = f.read()
with open(zipname, "wb") as f:
f.write(data_to_prepend)
f.write(zip_data)
class UncompressedZipImportTestCase(ImportHooksBaseTestCase): class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
compression = ZIP_STORED compression = ZIP_STORED
...@@ -79,9 +58,23 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase): ...@@ -79,9 +58,23 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
ImportHooksBaseTestCase.setUp(self) ImportHooksBaseTestCase.setUp(self)
def doTest(self, expected_ext, files, *modules, **kw): def doTest(self, expected_ext, files, *modules, **kw):
_write_zip_package(TEMP_ZIP, files, data_to_prepend=kw.get("stuff"), z = ZipFile(TEMP_ZIP, "w")
compression=self.compression)
try: try:
for name, (mtime, data) in files.items():
zinfo = ZipInfo(name, time.localtime(mtime))
zinfo.compress_type = self.compression
z.writestr(zinfo, data)
z.close()
stuff = kw.get("stuff", None)
if stuff is not None:
# Prepend 'stuff' to the start of the zipfile
with open(TEMP_ZIP, "rb") as f:
data = f.read()
with open(TEMP_ZIP, "wb") as f:
f.write(stuff)
f.write(data)
sys.path.insert(0, TEMP_ZIP) sys.path.insert(0, TEMP_ZIP)
mod = __import__(".".join(modules), globals(), locals(), mod = __import__(".".join(modules), globals(), locals(),
...@@ -96,8 +89,7 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase): ...@@ -96,8 +89,7 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
self.assertEqual(file, os.path.join(TEMP_ZIP, self.assertEqual(file, os.path.join(TEMP_ZIP,
*modules) + expected_ext) *modules) + expected_ext)
finally: finally:
while TEMP_ZIP in sys.path: z.close()
sys.path.remove(TEMP_ZIP)
os.remove(TEMP_ZIP) os.remove(TEMP_ZIP)
def testAFakeZlib(self): def testAFakeZlib(self):
...@@ -403,67 +395,10 @@ class CompressedZipImportTestCase(UncompressedZipImportTestCase): ...@@ -403,67 +395,10 @@ class CompressedZipImportTestCase(UncompressedZipImportTestCase):
compression = ZIP_DEFLATED compression = ZIP_DEFLATED
class ZipFileModifiedAfterImportTestCase(ImportHooksBaseTestCase):
def setUp(self):
zipimport._zip_directory_cache.clear()
zipimport._zip_stat_cache.clear()
ImportHooksBaseTestCase.setUp(self)
def tearDown(self):
ImportHooksBaseTestCase.tearDown(self)
if os.path.exists(TEMP_ZIP):
os.remove(TEMP_ZIP)
def testZipFileChangesAfterFirstImport(self):
"""Alter the zip file after caching its index and try an import."""
packdir = TESTPACK + os.sep
files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
packdir + TESTMOD + ".py": (NOW, "test_value = 38\n"),
"ziptest_a.py": (NOW, "test_value = 23\n"),
"ziptest_b.py": (NOW, "test_value = 42\n"),
"ziptest_c.py": (NOW, "test_value = 1337\n")}
zipfile_path = TEMP_ZIP
_write_zip_package(zipfile_path, files)
self.assertTrue(os.path.exists(zipfile_path))
sys.path.insert(0, zipfile_path)
# Import something out of the zipfile and confirm it is correct.
testmod = __import__(TESTPACK + "." + TESTMOD,
globals(), locals(), ["__dummy__"])
self.assertEqual(testmod.test_value, 38)
# Import something else out of the zipfile and confirm it is correct.
ziptest_b = __import__("ziptest_b", globals(), locals(), ["test_value"])
self.assertEqual(ziptest_b.test_value, 42)
# Truncate and fill the zip file with non-zip garbage.
with open(zipfile_path, "rb") as orig_zip_file:
orig_zip_file_contents = orig_zip_file.read()
with open(zipfile_path, "wb") as byebye_valid_zip_file:
byebye_valid_zip_file.write(b"Tear down this wall!\n"*1987)
# Now that the zipfile has been replaced, import something else from it
# which should fail as the file contents are now garbage.
with self.assertRaises(ImportError):
ziptest_a = __import__("ziptest_a", globals(), locals(),
["test_value"])
self.assertEqual(ziptest_a.test_value, 23)
# Now lets make it a valid zipfile that has some garbage at the start.
# This alters all of the offsets within the file
with open(zipfile_path, "wb") as new_zip_file:
new_zip_file.write(b"X"*1991) # The year Python was created.
new_zip_file.write(orig_zip_file_contents)
# Now that the zip file has been "restored" to a valid but different
# zipfile the zipimporter should *successfully* re-read the new zip
# file's end of file central index and be able to import from it again.
ziptest_c = __import__("ziptest_c", globals(), locals(), ["test_value"])
self.assertEqual(ziptest_c.test_value, 1337)
class BadFileZipImportTestCase(unittest.TestCase): class BadFileZipImportTestCase(unittest.TestCase):
def assertZipFailure(self, filename): def assertZipFailure(self, filename):
with self.assertRaises(zipimport.ZipImportError): self.assertRaises(zipimport.ZipImportError,
zipimport.zipimporter(filename) zipimport.zipimporter, filename)
def testNoFile(self): def testNoFile(self):
self.assertZipFailure('AdfjdkFJKDFJjdklfjs') self.assertZipFailure('AdfjdkFJKDFJjdklfjs')
...@@ -537,7 +472,6 @@ def test_main(): ...@@ -537,7 +472,6 @@ def test_main():
UncompressedZipImportTestCase, UncompressedZipImportTestCase,
CompressedZipImportTestCase, CompressedZipImportTestCase,
BadFileZipImportTestCase, BadFileZipImportTestCase,
ZipFileModifiedAfterImportTestCase,
) )
finally: finally:
support.unlink(TESTMOD) support.unlink(TESTMOD)
......
...@@ -45,16 +45,10 @@ struct _zipimporter { ...@@ -45,16 +45,10 @@ struct _zipimporter {
static PyObject *ZipImportError; static PyObject *ZipImportError;
/* read_directory() cache */ /* read_directory() cache */
static PyObject *zip_directory_cache = NULL; static PyObject *zip_directory_cache = NULL;
static PyObject *zip_stat_cache = NULL;
/* posix.fstat or nt.fstat function. Used due to posixmodule.c's
* superior fstat implementation over libc's on Windows. */
static PyObject *fstat_function = NULL; /* posix.fstat() or nt.fstat() */
/* forward decls */ /* forward decls */
static FILE *fopen_rb_and_stat(PyObject *path, PyObject **py_stat_p); static PyObject *read_directory(PyObject *archive);
static FILE *safely_reopen_archive(ZipImporter *self); static PyObject *get_data(PyObject *archive, PyObject *toc_entry);
static PyObject *read_directory(FILE *fp, PyObject *archive);
static PyObject *get_data(FILE *fp, PyObject *archive, PyObject *toc_entry);
static PyObject *get_module_code(ZipImporter *self, PyObject *fullname, static PyObject *get_module_code(ZipImporter *self, PyObject *fullname,
int *p_ispackage, PyObject **p_modpath); int *p_ispackage, PyObject **p_modpath);
...@@ -134,39 +128,11 @@ zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds) ...@@ -134,39 +128,11 @@ zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds)
files = PyDict_GetItem(zip_directory_cache, filename); files = PyDict_GetItem(zip_directory_cache, filename);
if (files == NULL) { if (files == NULL) {
PyObject *zip_stat = NULL; files = read_directory(filename);
FILE *fp = fopen_rb_and_stat(filename, &zip_stat); if (files == NULL)
if (fp == NULL) {
if (!PyErr_Occurred())
PyErr_Format(ZipImportError, "can't open Zip file: %R",
filename);
Py_XDECREF(zip_stat);
goto error; goto error;
} if (PyDict_SetItem(zip_directory_cache, filename, files) != 0)
if (Py_VerboseFlag)
PySys_FormatStderr("# zipimport: %U not cached, "
"reading TOC.\n", filename);
files = read_directory(fp, filename);
fclose(fp);
if (files == NULL) {
Py_XDECREF(zip_stat);
goto error;
}
if (PyDict_SetItem(zip_directory_cache, filename, files) != 0) {
Py_DECREF(files);
Py_XDECREF(zip_stat);
goto error; goto error;
}
if (zip_stat && PyDict_SetItem(zip_stat_cache, filename,
zip_stat) != 0) {
Py_DECREF(files);
Py_DECREF(zip_stat);
goto error;
}
Py_XDECREF(zip_stat);
} }
else else
Py_INCREF(files); Py_INCREF(files);
...@@ -588,11 +554,10 @@ zipimporter_get_data(PyObject *obj, PyObject *args) ...@@ -588,11 +554,10 @@ zipimporter_get_data(PyObject *obj, PyObject *args)
{ {
ZipImporter *self = (ZipImporter *)obj; ZipImporter *self = (ZipImporter *)obj;
PyObject *path, *key; PyObject *path, *key;
FILE *fp;
#ifdef ALTSEP #ifdef ALTSEP
_Py_IDENTIFIER(replace); _Py_IDENTIFIER(replace);
#endif #endif
PyObject *toc_entry, *data; PyObject *toc_entry;
Py_ssize_t path_start, path_len, len; Py_ssize_t path_start, path_len, len;
if (!PyArg_ParseTuple(args, "U:zipimporter.get_data", &path)) if (!PyArg_ParseTuple(args, "U:zipimporter.get_data", &path))
...@@ -620,23 +585,15 @@ zipimporter_get_data(PyObject *obj, PyObject *args) ...@@ -620,23 +585,15 @@ zipimporter_get_data(PyObject *obj, PyObject *args)
key = PyUnicode_Substring(path, path_start, path_len); key = PyUnicode_Substring(path, path_start, path_len);
if (key == NULL) if (key == NULL)
goto error; goto error;
fp = safely_reopen_archive(self);
if (fp == NULL)
goto error;
toc_entry = PyDict_GetItem(self->files, key); toc_entry = PyDict_GetItem(self->files, key);
if (toc_entry == NULL) { if (toc_entry == NULL) {
PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, key); PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, key);
Py_DECREF(key); Py_DECREF(key);
fclose(fp);
goto error; goto error;
} }
Py_DECREF(key); Py_DECREF(key);
Py_DECREF(path); Py_DECREF(path);
data = get_data(fp, self->archive, toc_entry); return get_data(self->archive, toc_entry);
fclose(fp);
return data;
error: error:
Py_DECREF(path); Py_DECREF(path);
return NULL; return NULL;
...@@ -661,7 +618,6 @@ zipimporter_get_source(PyObject *obj, PyObject *args) ...@@ -661,7 +618,6 @@ zipimporter_get_source(PyObject *obj, PyObject *args)
PyObject *toc_entry; PyObject *toc_entry;
PyObject *fullname, *subname, *path, *fullpath; PyObject *fullname, *subname, *path, *fullpath;
enum zi_module_info mi; enum zi_module_info mi;
FILE *fp;
if (!PyArg_ParseTuple(args, "U:zipimporter.get_source", &fullname)) if (!PyArg_ParseTuple(args, "U:zipimporter.get_source", &fullname))
return NULL; return NULL;
...@@ -691,18 +647,11 @@ zipimporter_get_source(PyObject *obj, PyObject *args) ...@@ -691,18 +647,11 @@ zipimporter_get_source(PyObject *obj, PyObject *args)
if (fullpath == NULL) if (fullpath == NULL)
return NULL; return NULL;
fp = safely_reopen_archive(self);
if (fp == NULL) {
Py_DECREF(fullpath);
return NULL;
}
toc_entry = PyDict_GetItem(self->files, fullpath); toc_entry = PyDict_GetItem(self->files, fullpath);
Py_DECREF(fullpath); Py_DECREF(fullpath);
if (toc_entry != NULL) { if (toc_entry != NULL) {
PyObject *res, *bytes; PyObject *res, *bytes;
bytes = get_data(fp, self->archive, toc_entry); bytes = get_data(self->archive, toc_entry);
fclose(fp);
if (bytes == NULL) if (bytes == NULL)
return NULL; return NULL;
res = PyUnicode_FromStringAndSize(PyBytes_AS_STRING(bytes), res = PyUnicode_FromStringAndSize(PyBytes_AS_STRING(bytes),
...@@ -710,10 +659,10 @@ zipimporter_get_source(PyObject *obj, PyObject *args) ...@@ -710,10 +659,10 @@ zipimporter_get_source(PyObject *obj, PyObject *args)
Py_DECREF(bytes); Py_DECREF(bytes);
return res; return res;
} }
fclose(fp);
/* we have the module, but no source */ /* we have the module, but no source */
Py_RETURN_NONE; Py_INCREF(Py_None);
return Py_None;
} }
PyDoc_STRVAR(doc_find_module, PyDoc_STRVAR(doc_find_module,
...@@ -879,135 +828,10 @@ get_long(unsigned char *buf) { ...@@ -879,135 +828,10 @@ get_long(unsigned char *buf) {
return x; return x;
} }
/* Return 1 if objects a and b fail a Py_EQ test for an attr. */
static int
compare_obj_attr_strings(PyObject *obj_a, PyObject *obj_b, char *attr_name)
{
int problem = 0;
PyObject *attr_a = PyObject_GetAttrString(obj_a, attr_name);
PyObject *attr_b = PyObject_GetAttrString(obj_b, attr_name);
if (attr_a == NULL || attr_b == NULL)
problem = 1;
else
problem = (PyObject_RichCompareBool(attr_a, attr_b, Py_EQ) != 1);
Py_XDECREF(attr_a);
Py_XDECREF(attr_b);
return problem;
}
/*
* Returns an open FILE * on success.
* Returns NULL on error with the Python error context set.
*/
static FILE *
safely_reopen_archive(ZipImporter *self)
{
FILE *fp;
PyObject *stat_now = NULL;
fp = fopen_rb_and_stat(self->archive, &stat_now);
if (!fp) {
PyErr_Format(ZipImportError,
"zipimport: can not open file %U", self->archive);
Py_XDECREF(stat_now);
return NULL;
}
if (stat_now != NULL) {
int problem = 0;
PyObject *files;
PyObject *prev_stat = PyDict_GetItem(zip_stat_cache, self->archive);
/* Test stat_now vs the old cached stat on some key attributes. */
if (prev_stat != NULL) {
problem = compare_obj_attr_strings(prev_stat, stat_now,
"st_ino");
problem |= compare_obj_attr_strings(prev_stat, stat_now,
"st_size");
problem |= compare_obj_attr_strings(prev_stat, stat_now,
"st_mtime");
} else {
if (Py_VerboseFlag)
PySys_FormatStderr("# zipimport: no stat data for %U!\n",
self->archive);
problem = 1;
}
if (problem) {
if (Py_VerboseFlag)
PySys_FormatStderr("# zipimport: %U modified since last"
" import, rereading TOC.\n", self->archive);
files = read_directory(fp, self->archive);
if (files == NULL) {
Py_DECREF(stat_now);
fclose(fp);
return NULL;
}
if (PyDict_SetItem(zip_directory_cache, self->archive,
files) != 0) {
Py_DECREF(files);
Py_DECREF(stat_now);
fclose(fp);
return NULL;
}
if (stat_now && PyDict_SetItem(zip_stat_cache, self->archive,
stat_now) != 0) {
Py_DECREF(files);
Py_DECREF(stat_now);
fclose(fp);
return NULL;
}
Py_XDECREF(self->files); /* free the old value. */
self->files = files;
} else {
/* No problem, discard the new stat data. */
Py_DECREF(stat_now);
}
} /* stat succeeded */
return fp;
}
/*
fopen_rb_and_stat(path, &py_stat) -> FILE *
Opens path in "rb" mode and populates the Python py_stat stat_result
with information about the opened file. *py_stat may not be changed
if there is no fstat_function or if fstat_function fails.
Returns NULL and does nothing to *py_stat if the open failed.
*/
static FILE *
fopen_rb_and_stat(PyObject *path, PyObject **py_stat_p)
{
FILE *fp;
assert(py_stat_p != NULL);
assert(*py_stat_p == NULL);
fp = _Py_fopen(path, "rb");
if (fp == NULL) {
if (!PyErr_Occurred())
PyErr_Format(ZipImportError,
"zipimport: can not open file %U", path);
return NULL;
}
if (fstat_function) {
PyObject *stat_result = PyObject_CallFunction(fstat_function,
"i", fileno(fp));
if (stat_result == NULL) {
PyErr_Clear(); /* We can function without it. */
} else {
*py_stat_p = stat_result;
}
}
return fp;
}
/* /*
read_directory(fp, archive) -> files dict (new reference) read_directory(archive) -> files dict (new reference)
Given an open Zip archive, build a dict, mapping file names Given a path to a Zip archive, build a dict, mapping file names
(local to the archive, using SEP as a separator) to toc entries. (local to the archive, using SEP as a separator) to toc entries.
A toc_entry is a tuple: A toc_entry is a tuple:
...@@ -1027,9 +851,10 @@ fopen_rb_and_stat(PyObject *path, PyObject **py_stat_p) ...@@ -1027,9 +851,10 @@ fopen_rb_and_stat(PyObject *path, PyObject **py_stat_p)
data_size and file_offset are 0. data_size and file_offset are 0.
*/ */
static PyObject * static PyObject *
read_directory(FILE *fp, PyObject *archive) read_directory(PyObject *archive)
{ {
PyObject *files = NULL; PyObject *files = NULL;
FILE *fp;
unsigned short flags; unsigned short flags;
short compress, time, date, name_size; short compress, time, date, name_size;
long crc, data_size, file_size, header_size; long crc, data_size, file_size, header_size;
...@@ -1044,18 +869,27 @@ read_directory(FILE *fp, PyObject *archive) ...@@ -1044,18 +869,27 @@ read_directory(FILE *fp, PyObject *archive)
const char *charset; const char *charset;
int bootstrap; int bootstrap;
assert(fp != NULL); fp = _Py_fopen(archive, "rb");
if (fp == NULL) {
if (!PyErr_Occurred())
PyErr_Format(ZipImportError, "can't open Zip file: %R", archive);
return NULL;
}
if (fseek(fp, -22, SEEK_END) == -1) { if (fseek(fp, -22, SEEK_END) == -1) {
fclose(fp);
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
return NULL; return NULL;
} }
header_position = ftell(fp); header_position = ftell(fp);
if (fread(endof_central_dir, 1, 22, fp) != 22) { if (fread(endof_central_dir, 1, 22, fp) != 22) {
fclose(fp);
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
return NULL; return NULL;
} }
if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) { if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) {
/* Bad: End of Central Dir signature */ /* Bad: End of Central Dir signature */
fclose(fp);
PyErr_Format(ZipImportError, "not a Zip file: %R", archive); PyErr_Format(ZipImportError, "not a Zip file: %R", archive);
return NULL; return NULL;
} }
...@@ -1149,16 +983,19 @@ read_directory(FILE *fp, PyObject *archive) ...@@ -1149,16 +983,19 @@ read_directory(FILE *fp, PyObject *archive)
goto error; goto error;
count++; count++;
} }
fclose(fp);
if (Py_VerboseFlag) if (Py_VerboseFlag)
PySys_FormatStderr("# zipimport: found %ld names in %R\n", PySys_FormatStderr("# zipimport: found %ld names in %R\n",
count, archive); count, archive);
return files; return files;
fseek_error: fseek_error:
fclose(fp);
Py_XDECREF(files); Py_XDECREF(files);
Py_XDECREF(nameobj); Py_XDECREF(nameobj);
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
return NULL; return NULL;
error: error:
fclose(fp);
Py_XDECREF(files); Py_XDECREF(files);
Py_XDECREF(nameobj); Py_XDECREF(nameobj);
return NULL; return NULL;
...@@ -1197,13 +1034,14 @@ get_decompress_func(void) ...@@ -1197,13 +1034,14 @@ get_decompress_func(void)
return decompress; return decompress;
} }
/* Given a FILE* to a Zip file and a toc_entry, return the (uncompressed) /* Given a path to a Zip file and a toc_entry, return the (uncompressed)
data as a new reference. */ data as a new reference. */
static PyObject * static PyObject *
get_data(FILE *fp, PyObject *archive, PyObject *toc_entry) get_data(PyObject *archive, PyObject *toc_entry)
{ {
PyObject *raw_data, *data = NULL, *decompress; PyObject *raw_data, *data = NULL, *decompress;
char *buf; char *buf;
FILE *fp;
int err; int err;
Py_ssize_t bytes_read = 0; Py_ssize_t bytes_read = 0;
long l; long l;
...@@ -1217,8 +1055,17 @@ get_data(FILE *fp, PyObject *archive, PyObject *toc_entry) ...@@ -1217,8 +1055,17 @@ get_data(FILE *fp, PyObject *archive, PyObject *toc_entry)
return NULL; return NULL;
} }
fp = _Py_fopen(archive, "rb");
if (!fp) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_IOError,
"zipimport: can not open file %U", archive);
return NULL;
}
/* Check to make sure the local file header is correct */ /* Check to make sure the local file header is correct */
if (fseek(fp, file_offset, 0) == -1) { if (fseek(fp, file_offset, 0) == -1) {
fclose(fp);
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
return NULL; return NULL;
} }
...@@ -1229,9 +1076,11 @@ get_data(FILE *fp, PyObject *archive, PyObject *toc_entry) ...@@ -1229,9 +1076,11 @@ get_data(FILE *fp, PyObject *archive, PyObject *toc_entry)
PyErr_Format(ZipImportError, PyErr_Format(ZipImportError,
"bad local file header in %U", "bad local file header in %U",
archive); archive);
fclose(fp);
return NULL; return NULL;
} }
if (fseek(fp, file_offset + 26, 0) == -1) { if (fseek(fp, file_offset + 26, 0) == -1) {
fclose(fp);
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
return NULL; return NULL;
} }
...@@ -1246,6 +1095,7 @@ get_data(FILE *fp, PyObject *archive, PyObject *toc_entry) ...@@ -1246,6 +1095,7 @@ get_data(FILE *fp, PyObject *archive, PyObject *toc_entry)
raw_data = PyBytes_FromStringAndSize((char *)NULL, bytes_size); raw_data = PyBytes_FromStringAndSize((char *)NULL, bytes_size);
if (raw_data == NULL) { if (raw_data == NULL) {
fclose(fp);
return NULL; return NULL;
} }
buf = PyBytes_AsString(raw_data); buf = PyBytes_AsString(raw_data);
...@@ -1254,9 +1104,11 @@ get_data(FILE *fp, PyObject *archive, PyObject *toc_entry) ...@@ -1254,9 +1104,11 @@ get_data(FILE *fp, PyObject *archive, PyObject *toc_entry)
if (err == 0) { if (err == 0) {
bytes_read = fread(buf, 1, data_size, fp); bytes_read = fread(buf, 1, data_size, fp);
} else { } else {
fclose(fp);
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
return NULL; return NULL;
} }
fclose(fp);
if (err || bytes_read != data_size) { if (err || bytes_read != data_size) {
PyErr_SetString(PyExc_IOError, PyErr_SetString(PyExc_IOError,
"zipimport: can't read data"); "zipimport: can't read data");
...@@ -1477,12 +1329,12 @@ get_mtime_of_source(ZipImporter *self, PyObject *path) ...@@ -1477,12 +1329,12 @@ get_mtime_of_source(ZipImporter *self, PyObject *path)
/* Return the code object for the module named by 'fullname' from the /* Return the code object for the module named by 'fullname' from the
Zip archive as a new reference. */ Zip archive as a new reference. */
static PyObject * static PyObject *
get_code_from_data(ZipImporter *self, FILE *fp, int ispackage, int isbytecode, get_code_from_data(ZipImporter *self, int ispackage, int isbytecode,
time_t mtime, PyObject *toc_entry) time_t mtime, PyObject *toc_entry)
{ {
PyObject *data, *modpath, *code; PyObject *data, *modpath, *code;
data = get_data(fp, self->archive, toc_entry); data = get_data(self->archive, toc_entry);
if (data == NULL) if (data == NULL)
return NULL; return NULL;
...@@ -1504,7 +1356,6 @@ get_module_code(ZipImporter *self, PyObject *fullname, ...@@ -1504,7 +1356,6 @@ get_module_code(ZipImporter *self, PyObject *fullname,
PyObject *code = NULL, *toc_entry, *subname; PyObject *code = NULL, *toc_entry, *subname;
PyObject *path, *fullpath = NULL; PyObject *path, *fullpath = NULL;
struct st_zip_searchorder *zso; struct st_zip_searchorder *zso;
FILE *fp;
subname = get_subname(fullname); subname = get_subname(fullname);
if (subname == NULL) if (subname == NULL)
...@@ -1515,12 +1366,6 @@ get_module_code(ZipImporter *self, PyObject *fullname, ...@@ -1515,12 +1366,6 @@ get_module_code(ZipImporter *self, PyObject *fullname,
if (path == NULL) if (path == NULL)
return NULL; return NULL;
fp = safely_reopen_archive(self);
if (fp == NULL) {
Py_DECREF(path);
return NULL;
}
for (zso = zip_searchorder; *zso->suffix; zso++) { for (zso = zip_searchorder; *zso->suffix; zso++) {
code = NULL; code = NULL;
...@@ -1531,7 +1376,6 @@ get_module_code(ZipImporter *self, PyObject *fullname, ...@@ -1531,7 +1376,6 @@ get_module_code(ZipImporter *self, PyObject *fullname,
if (Py_VerboseFlag > 1) if (Py_VerboseFlag > 1)
PySys_FormatStderr("# trying %U%c%U\n", PySys_FormatStderr("# trying %U%c%U\n",
self->archive, (int)SEP, fullpath); self->archive, (int)SEP, fullpath);
toc_entry = PyDict_GetItem(self->files, fullpath); toc_entry = PyDict_GetItem(self->files, fullpath);
if (toc_entry != NULL) { if (toc_entry != NULL) {
time_t mtime = 0; time_t mtime = 0;
...@@ -1547,7 +1391,7 @@ get_module_code(ZipImporter *self, PyObject *fullname, ...@@ -1547,7 +1391,7 @@ get_module_code(ZipImporter *self, PyObject *fullname,
Py_CLEAR(fullpath); Py_CLEAR(fullpath);
if (p_ispackage != NULL) if (p_ispackage != NULL)
*p_ispackage = ispackage; *p_ispackage = ispackage;
code = get_code_from_data(self, fp, ispackage, code = get_code_from_data(self, ispackage,
isbytecode, mtime, isbytecode, mtime,
toc_entry); toc_entry);
if (code == Py_None) { if (code == Py_None) {
...@@ -1567,7 +1411,6 @@ get_module_code(ZipImporter *self, PyObject *fullname, ...@@ -1567,7 +1411,6 @@ get_module_code(ZipImporter *self, PyObject *fullname,
} }
PyErr_Format(ZipImportError, "can't find module %R", fullname); PyErr_Format(ZipImportError, "can't find module %R", fullname);
exit: exit:
fclose(fp);
Py_DECREF(path); Py_DECREF(path);
Py_XDECREF(fullpath); Py_XDECREF(fullpath);
return code; return code;
...@@ -1585,8 +1428,6 @@ This module exports three objects:\n\ ...@@ -1585,8 +1428,6 @@ This module exports three objects:\n\
subclass of ImportError, so it can be caught as ImportError, too.\n\ subclass of ImportError, so it can be caught as ImportError, too.\n\
- _zip_directory_cache: a dict, mapping archive paths to zip directory\n\ - _zip_directory_cache: a dict, mapping archive paths to zip directory\n\
info dicts, as used in zipimporter._files.\n\ info dicts, as used in zipimporter._files.\n\
- _zip_stat_cache: a dict, mapping archive paths to stat_result\n\
info for the .zip the last time anything was imported from it.\n\
\n\ \n\
It is usually not needed to use the zipimport module explicitly; it is\n\ It is usually not needed to use the zipimport module explicitly; it is\n\
used by the builtin import mechanism for sys.path items that are paths\n\ used by the builtin import mechanism for sys.path items that are paths\n\
...@@ -1646,7 +1487,6 @@ PyInit_zipimport(void) ...@@ -1646,7 +1487,6 @@ PyInit_zipimport(void)
(PyObject *)&ZipImporter_Type) < 0) (PyObject *)&ZipImporter_Type) < 0)
return NULL; return NULL;
Py_XDECREF(zip_directory_cache); /* Avoid embedded interpreter leaks. */
zip_directory_cache = PyDict_New(); zip_directory_cache = PyDict_New();
if (zip_directory_cache == NULL) if (zip_directory_cache == NULL)
return NULL; return NULL;
...@@ -1654,36 +1494,5 @@ PyInit_zipimport(void) ...@@ -1654,36 +1494,5 @@ PyInit_zipimport(void)
if (PyModule_AddObject(mod, "_zip_directory_cache", if (PyModule_AddObject(mod, "_zip_directory_cache",
zip_directory_cache) < 0) zip_directory_cache) < 0)
return NULL; return NULL;
Py_XDECREF(zip_stat_cache); /* Avoid embedded interpreter leaks. */
zip_stat_cache = PyDict_New();
if (zip_stat_cache == NULL)
return NULL;
Py_INCREF(zip_stat_cache);
if (PyModule_AddObject(mod, "_zip_stat_cache", zip_stat_cache) < 0)
return NULL;
{
/* We cannot import "os" here as that is a .py/.pyc file that could
* live within a zipped up standard library. Import the posix or nt
* builtin that provides the fstat() function we want instead. */
PyObject *os_like_module;
Py_CLEAR(fstat_function); /* Avoid embedded interpreter leaks. */
os_like_module = PyImport_ImportModule("posix");
if (os_like_module == NULL) {
PyErr_Clear();
os_like_module = PyImport_ImportModule("nt");
}
if (os_like_module != NULL) {
fstat_function = PyObject_GetAttrString(os_like_module, "fstat");
Py_DECREF(os_like_module);
}
if (fstat_function == NULL) {
PyErr_Clear(); /* non-fatal, we'll go on without it. */
if (Py_VerboseFlag)
PySys_WriteStderr("# zipimport unable to use os.fstat().\n");
}
}
return mod; return mod;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment