mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Issue #19883: Fixed possible integer overflows in zipimport.
This commit is contained in:
commit
8abaa9ab34
2 changed files with 219 additions and 156 deletions
|
@ -159,6 +159,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #19883: Fixed possible integer overflows in zipimport.
|
||||||
|
|
||||||
- Issue #26227: On Windows, getnameinfo(), gethostbyaddr() and
|
- Issue #26227: On Windows, getnameinfo(), gethostbyaddr() and
|
||||||
gethostbyname_ex() functions of the socket module now decode the hostname
|
gethostbyname_ex() functions of the socket module now decode the hostname
|
||||||
from the ANSI code page rather than UTF-8.
|
from the ANSI code page rather than UTF-8.
|
||||||
|
|
|
@ -827,23 +827,43 @@ static PyTypeObject ZipImporter_Type = {
|
||||||
|
|
||||||
/* implementation */
|
/* implementation */
|
||||||
|
|
||||||
/* Given a buffer, return the long that is represented by the first
|
/* Given a buffer, return the unsigned int that is represented by the first
|
||||||
4 bytes, encoded as little endian. This partially reimplements
|
4 bytes, encoded as little endian. This partially reimplements
|
||||||
marshal.c:r_long() */
|
marshal.c:r_long() */
|
||||||
static long
|
static unsigned int
|
||||||
get_long(const unsigned char *buf) {
|
get_uint32(const unsigned char *buf)
|
||||||
long x;
|
{
|
||||||
|
unsigned int x;
|
||||||
x = buf[0];
|
x = buf[0];
|
||||||
x |= (long)buf[1] << 8;
|
x |= (unsigned int)buf[1] << 8;
|
||||||
x |= (long)buf[2] << 16;
|
x |= (unsigned int)buf[2] << 16;
|
||||||
x |= (long)buf[3] << 24;
|
x |= (unsigned int)buf[3] << 24;
|
||||||
#if SIZEOF_LONG > 4
|
|
||||||
/* Sign extension for 64-bit machines */
|
|
||||||
x |= -(x & 0x80000000L);
|
|
||||||
#endif
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given a buffer, return the unsigned int that is represented by the first
|
||||||
|
2 bytes, encoded as little endian. This partially reimplements
|
||||||
|
marshal.c:r_short() */
|
||||||
|
static unsigned short
|
||||||
|
get_uint16(const unsigned char *buf)
|
||||||
|
{
|
||||||
|
unsigned short x;
|
||||||
|
x = buf[0];
|
||||||
|
x |= (unsigned short)buf[1] << 8;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_file_error(PyObject *archive, int eof)
|
||||||
|
{
|
||||||
|
if (eof) {
|
||||||
|
PyErr_SetString(PyExc_EOFError, "EOF read where not expected");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, archive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
read_directory(archive) -> files dict (new reference)
|
read_directory(archive) -> files dict (new reference)
|
||||||
|
|
||||||
|
@ -871,20 +891,18 @@ read_directory(PyObject *archive)
|
||||||
{
|
{
|
||||||
PyObject *files = NULL;
|
PyObject *files = NULL;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
unsigned short flags;
|
unsigned short flags, compress, time, date, name_size;
|
||||||
short compress, time, date, name_size;
|
unsigned int crc, data_size, file_size, header_size, header_offset;
|
||||||
long crc, data_size, file_size, header_size;
|
unsigned long file_offset, header_position;
|
||||||
Py_ssize_t file_offset, header_position, header_offset;
|
unsigned long arc_offset; /* Absolute offset to start of the zip-archive. */
|
||||||
long l, count;
|
unsigned int count, i;
|
||||||
Py_ssize_t i;
|
unsigned char buffer[46];
|
||||||
char name[MAXPATHLEN + 5];
|
char name[MAXPATHLEN + 5];
|
||||||
char dummy[8]; /* Buffer to read unused header values into */
|
|
||||||
PyObject *nameobj = NULL;
|
PyObject *nameobj = NULL;
|
||||||
char *p, endof_central_dir[22];
|
|
||||||
Py_ssize_t arc_offset; /* Absolute offset to start of the zip-archive. */
|
|
||||||
PyObject *path;
|
PyObject *path;
|
||||||
const char *charset;
|
const char *charset;
|
||||||
int bootstrap;
|
int bootstrap;
|
||||||
|
const char *errmsg = NULL;
|
||||||
|
|
||||||
fp = _Py_fopen_obj(archive, "rb");
|
fp = _Py_fopen_obj(archive, "rb");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
|
@ -898,91 +916,112 @@ read_directory(PyObject *archive)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fseek(fp, -22, SEEK_END) == -1) {
|
if (fseek(fp, -22, SEEK_END) == -1) {
|
||||||
fclose(fp);
|
goto file_error;
|
||||||
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
header_position = ftell(fp);
|
header_position = (unsigned long)ftell(fp);
|
||||||
if (fread(endof_central_dir, 1, 22, fp) != 22) {
|
if (header_position == (unsigned long)-1) {
|
||||||
fclose(fp);
|
goto file_error;
|
||||||
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) {
|
assert(header_position <= (unsigned long)LONG_MAX);
|
||||||
|
if (fread(buffer, 1, 22, fp) != 22) {
|
||||||
|
goto file_error;
|
||||||
|
}
|
||||||
|
if (get_uint32(buffer) != 0x06054B50u) {
|
||||||
/* Bad: End of Central Dir signature */
|
/* Bad: End of Central Dir signature */
|
||||||
fclose(fp);
|
errmsg = "not a Zip file";
|
||||||
PyErr_Format(ZipImportError, "not a Zip file: %R", archive);
|
goto invalid_header;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header_size = get_long((unsigned char *)endof_central_dir + 12);
|
header_size = get_uint32(buffer + 12);
|
||||||
header_offset = get_long((unsigned char *)endof_central_dir + 16);
|
header_offset = get_uint32(buffer + 16);
|
||||||
arc_offset = header_position - header_offset - header_size;
|
if (header_position < header_size) {
|
||||||
header_offset += arc_offset;
|
errmsg = "bad central directory size";
|
||||||
|
goto invalid_header;
|
||||||
|
}
|
||||||
|
if (header_position < header_offset) {
|
||||||
|
errmsg = "bad central directory offset";
|
||||||
|
goto invalid_header;
|
||||||
|
}
|
||||||
|
if (header_position - header_size < header_offset) {
|
||||||
|
errmsg = "bad central directory size or offset";
|
||||||
|
goto invalid_header;
|
||||||
|
}
|
||||||
|
header_position -= header_size;
|
||||||
|
arc_offset = header_position - header_offset;
|
||||||
|
|
||||||
files = PyDict_New();
|
files = PyDict_New();
|
||||||
if (files == NULL)
|
if (files == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
/* Start of Central Directory */
|
/* Start of Central Directory */
|
||||||
count = 0;
|
count = 0;
|
||||||
if (fseek(fp, header_offset, 0) == -1)
|
if (fseek(fp, (long)header_position, 0) == -1) {
|
||||||
goto file_error;
|
goto file_error;
|
||||||
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
PyObject *t;
|
PyObject *t;
|
||||||
|
size_t n;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* Start of file header */
|
n = fread(buffer, 1, 46, fp);
|
||||||
l = PyMarshal_ReadLongFromFile(fp);
|
if (n < 4) {
|
||||||
if (l == -1 && PyErr_Occurred())
|
goto eof_error;
|
||||||
goto error;
|
|
||||||
if (l != 0x02014B50)
|
|
||||||
break; /* Bad: Central Dir File Header */
|
|
||||||
|
|
||||||
/* On Windows, calling fseek to skip over the fields we don't use is
|
|
||||||
slower than reading the data into a dummy buffer because fseek flushes
|
|
||||||
stdio's internal buffers. See issue #8745. */
|
|
||||||
if (fread(dummy, 1, 4, fp) != 4) /* Skip unused fields, avoid fseek */
|
|
||||||
goto file_error;
|
|
||||||
|
|
||||||
flags = (unsigned short)PyMarshal_ReadShortFromFile(fp);
|
|
||||||
compress = PyMarshal_ReadShortFromFile(fp);
|
|
||||||
time = PyMarshal_ReadShortFromFile(fp);
|
|
||||||
date = PyMarshal_ReadShortFromFile(fp);
|
|
||||||
crc = PyMarshal_ReadLongFromFile(fp);
|
|
||||||
data_size = PyMarshal_ReadLongFromFile(fp);
|
|
||||||
file_size = PyMarshal_ReadLongFromFile(fp);
|
|
||||||
name_size = PyMarshal_ReadShortFromFile(fp);
|
|
||||||
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;
|
|
||||||
if (PyErr_Occurred())
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (name_size > MAXPATHLEN)
|
|
||||||
name_size = MAXPATHLEN;
|
|
||||||
|
|
||||||
p = name;
|
|
||||||
for (i = 0; i < (Py_ssize_t)name_size; i++) {
|
|
||||||
*p = (char)getc(fp);
|
|
||||||
if (*p == '/')
|
|
||||||
*p = SEP;
|
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
*p = 0; /* Add terminating null byte */
|
/* Start of file header */
|
||||||
for (; i < header_size; i++) /* Skip the rest of the header */
|
if (get_uint32(buffer) != 0x02014B50u) {
|
||||||
if(getc(fp) == EOF) /* Avoid fseek */
|
break; /* Bad: Central Dir File Header */
|
||||||
|
}
|
||||||
|
if (n != 46) {
|
||||||
|
goto eof_error;
|
||||||
|
}
|
||||||
|
flags = get_uint16(buffer + 8);
|
||||||
|
compress = get_uint16(buffer + 10);
|
||||||
|
time = get_uint16(buffer + 12);
|
||||||
|
date = get_uint16(buffer + 14);
|
||||||
|
crc = get_uint32(buffer + 16);
|
||||||
|
data_size = get_uint32(buffer + 20);
|
||||||
|
file_size = get_uint32(buffer + 24);
|
||||||
|
name_size = get_uint16(buffer + 28);
|
||||||
|
header_size = (unsigned int)name_size +
|
||||||
|
get_uint16(buffer + 30) /* extra field */ +
|
||||||
|
get_uint16(buffer + 32) /* comment */;
|
||||||
|
|
||||||
|
file_offset = get_uint32(buffer + 42);
|
||||||
|
if (file_offset > header_offset) {
|
||||||
|
errmsg = "bad local header offset";
|
||||||
|
goto invalid_header;
|
||||||
|
}
|
||||||
|
file_offset += arc_offset;
|
||||||
|
|
||||||
|
if (name_size > MAXPATHLEN) {
|
||||||
|
name_size = MAXPATHLEN;
|
||||||
|
}
|
||||||
|
if (fread(name, 1, name_size, fp) != name_size) {
|
||||||
|
goto file_error;
|
||||||
|
}
|
||||||
|
name[name_size] = '\0'; /* Add terminating null byte */
|
||||||
|
if (SEP != '/') {
|
||||||
|
for (i = 0; i < name_size; i++) {
|
||||||
|
if (name[i] == '/') {
|
||||||
|
name[i] = SEP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Skip the rest of the header.
|
||||||
|
* On Windows, calling fseek to skip over the fields we don't use is
|
||||||
|
* slower than reading the data because fseek flushes stdio's
|
||||||
|
* internal buffers. See issue #8745. */
|
||||||
|
assert(header_size <= 3*0xFFFFu);
|
||||||
|
for (i = name_size; i < header_size; i++) {
|
||||||
|
if (getc(fp) == EOF) {
|
||||||
goto file_error;
|
goto file_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bootstrap = 0;
|
bootstrap = 0;
|
||||||
if (flags & 0x0800)
|
if (flags & 0x0800) {
|
||||||
charset = "utf-8";
|
charset = "utf-8";
|
||||||
|
}
|
||||||
else if (!PyThreadState_GET()->interp->codecs_initialized) {
|
else if (!PyThreadState_GET()->interp->codecs_initialized) {
|
||||||
/* During bootstrap, we may need to load the encodings
|
/* During bootstrap, we may need to load the encodings
|
||||||
package from a ZIP file. But the cp437 encoding is implemented
|
package from a ZIP file. But the cp437 encoding is implemented
|
||||||
|
@ -993,44 +1032,59 @@ read_directory(PyObject *archive)
|
||||||
charset = "ascii";
|
charset = "ascii";
|
||||||
bootstrap = 1;
|
bootstrap = 1;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
charset = "cp437";
|
charset = "cp437";
|
||||||
|
}
|
||||||
nameobj = PyUnicode_Decode(name, name_size, charset, NULL);
|
nameobj = PyUnicode_Decode(name, name_size, charset, NULL);
|
||||||
if (nameobj == NULL) {
|
if (nameobj == NULL) {
|
||||||
if (bootstrap)
|
if (bootstrap) {
|
||||||
PyErr_Format(PyExc_NotImplementedError,
|
PyErr_Format(PyExc_NotImplementedError,
|
||||||
"bootstrap issue: python%i%i.zip contains non-ASCII "
|
"bootstrap issue: python%i%i.zip contains non-ASCII "
|
||||||
"filenames without the unicode flag",
|
"filenames without the unicode flag",
|
||||||
PY_MAJOR_VERSION, PY_MINOR_VERSION);
|
PY_MAJOR_VERSION, PY_MINOR_VERSION);
|
||||||
|
}
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (PyUnicode_READY(nameobj) == -1)
|
if (PyUnicode_READY(nameobj) == -1) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
path = PyUnicode_FromFormat("%U%c%U", archive, SEP, nameobj);
|
path = PyUnicode_FromFormat("%U%c%U", archive, SEP, nameobj);
|
||||||
if (path == NULL)
|
if (path == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
t = Py_BuildValue("Nhllnhhl", path, compress, data_size,
|
}
|
||||||
|
t = Py_BuildValue("NHIIkHHI", path, compress, data_size,
|
||||||
file_size, file_offset, time, date, crc);
|
file_size, file_offset, time, date, crc);
|
||||||
if (t == NULL)
|
if (t == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
err = PyDict_SetItem(files, nameobj, t);
|
err = PyDict_SetItem(files, nameobj, t);
|
||||||
Py_CLEAR(nameobj);
|
Py_CLEAR(nameobj);
|
||||||
Py_DECREF(t);
|
Py_DECREF(t);
|
||||||
if (err != 0)
|
if (err != 0) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag) {
|
||||||
PySys_FormatStderr("# zipimport: found %ld names in %R\n",
|
PySys_FormatStderr("# zipimport: found %u names in %R\n",
|
||||||
count, archive);
|
count, archive);
|
||||||
|
}
|
||||||
return files;
|
return files;
|
||||||
|
|
||||||
|
eof_error:
|
||||||
|
set_file_error(archive, !ferror(fp));
|
||||||
|
goto error;
|
||||||
|
|
||||||
file_error:
|
file_error:
|
||||||
fclose(fp);
|
|
||||||
Py_XDECREF(files);
|
|
||||||
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;
|
goto error;
|
||||||
|
|
||||||
|
invalid_header:
|
||||||
|
assert(errmsg != NULL);
|
||||||
|
PyErr_Format(ZipImportError, "%s: %R", errmsg, archive);
|
||||||
|
goto error;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
Py_XDECREF(files);
|
Py_XDECREF(files);
|
||||||
|
@ -1076,17 +1130,18 @@ get_decompress_func(void)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
get_data(PyObject *archive, PyObject *toc_entry)
|
get_data(PyObject *archive, PyObject *toc_entry)
|
||||||
{
|
{
|
||||||
PyObject *raw_data, *data = NULL, *decompress;
|
PyObject *raw_data = NULL, *data, *decompress;
|
||||||
char *buf;
|
char *buf;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int err;
|
|
||||||
Py_ssize_t bytes_read = 0;
|
|
||||||
long l;
|
|
||||||
PyObject *datapath;
|
PyObject *datapath;
|
||||||
long compress, data_size, file_size, file_offset, bytes_size;
|
unsigned short compress, time, date;
|
||||||
long time, date, crc;
|
unsigned int crc;
|
||||||
|
Py_ssize_t data_size, file_size, bytes_size;
|
||||||
|
long file_offset, header_size;
|
||||||
|
unsigned char buffer[30];
|
||||||
|
const char *errmsg = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(toc_entry, "Olllllll", &datapath, &compress,
|
if (!PyArg_ParseTuple(toc_entry, "OHnnlHHI", &datapath, &compress,
|
||||||
&data_size, &file_size, &file_offset, &time,
|
&data_size, &file_size, &file_offset, &time,
|
||||||
&date, &crc)) {
|
&date, &crc)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1097,39 +1152,30 @@ get_data(PyObject *archive, PyObject *toc_entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = _Py_fopen_obj(archive, "rb");
|
fp = _Py_fopen_obj(archive, "rb");
|
||||||
if (!fp)
|
if (!fp) {
|
||||||
return NULL;
|
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);
|
goto file_error;
|
||||||
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
if (fread(buffer, 1, 30, fp) != 30) {
|
||||||
l = PyMarshal_ReadLongFromFile(fp);
|
goto eof_error;
|
||||||
if (l != 0x04034B50) {
|
}
|
||||||
|
if (get_uint32(buffer) != 0x04034B50u) {
|
||||||
/* Bad: Local File Header */
|
/* Bad: Local File Header */
|
||||||
if (!PyErr_Occurred())
|
errmsg = "bad local file header";
|
||||||
PyErr_Format(ZipImportError,
|
goto invalid_header;
|
||||||
"bad local file header in %U",
|
|
||||||
archive);
|
|
||||||
fclose(fp);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (fseek(fp, file_offset + 26, 0) == -1) {
|
|
||||||
fclose(fp);
|
|
||||||
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l = 30 + PyMarshal_ReadShortFromFile(fp) +
|
header_size = (unsigned int)30 +
|
||||||
PyMarshal_ReadShortFromFile(fp); /* local header size */
|
get_uint16(buffer + 26) /* file name */ +
|
||||||
if (PyErr_Occurred()) {
|
get_uint16(buffer + 28) /* extra field */;
|
||||||
fclose(fp);
|
if (file_offset > LONG_MAX - header_size) {
|
||||||
return NULL;
|
errmsg = "bad local file header size";
|
||||||
|
goto invalid_header;
|
||||||
}
|
}
|
||||||
file_offset += l; /* Start of file data */
|
file_offset += header_size; /* Start of file data */
|
||||||
|
|
||||||
if (data_size > LONG_MAX - 1) {
|
if (data_size > LONG_MAX - 1) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
@ -1137,33 +1183,27 @@ get_data(PyObject *archive, PyObject *toc_entry)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
bytes_size = compress == 0 ? data_size : data_size + 1;
|
bytes_size = compress == 0 ? data_size : data_size + 1;
|
||||||
if (bytes_size == 0)
|
if (bytes_size == 0) {
|
||||||
bytes_size++;
|
bytes_size++;
|
||||||
|
}
|
||||||
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);
|
goto error;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
buf = PyBytes_AsString(raw_data);
|
buf = PyBytes_AsString(raw_data);
|
||||||
|
|
||||||
err = fseek(fp, file_offset, 0);
|
if (fseek(fp, file_offset, 0) == -1) {
|
||||||
if (err == 0) {
|
goto file_error;
|
||||||
bytes_read = fread(buf, 1, data_size, fp);
|
|
||||||
} else {
|
|
||||||
fclose(fp);
|
|
||||||
Py_DECREF(raw_data);
|
|
||||||
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
fclose(fp);
|
if (fread(buf, 1, data_size, fp) != (size_t)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");
|
||||||
Py_DECREF(raw_data);
|
goto error;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
fp = NULL;
|
||||||
|
|
||||||
if (compress != 0) {
|
if (compress != 0) {
|
||||||
buf[data_size] = 'Z'; /* saw this in zipfile.py */
|
buf[data_size] = 'Z'; /* saw this in zipfile.py */
|
||||||
data_size++;
|
data_size++;
|
||||||
|
@ -1186,9 +1226,28 @@ get_data(PyObject *archive, PyObject *toc_entry)
|
||||||
}
|
}
|
||||||
data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
|
data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
|
||||||
Py_DECREF(decompress);
|
Py_DECREF(decompress);
|
||||||
error:
|
|
||||||
Py_DECREF(raw_data);
|
Py_DECREF(raw_data);
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
|
eof_error:
|
||||||
|
set_file_error(archive, !ferror(fp));
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
file_error:
|
||||||
|
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
invalid_header:
|
||||||
|
assert(errmsg != NULL);
|
||||||
|
PyErr_Format(ZipImportError, "%s: %R", errmsg, archive);
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (fp != NULL) {
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
Py_XDECREF(raw_data);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lenient date/time comparison function. The precision of the mtime
|
/* Lenient date/time comparison function. The precision of the mtime
|
||||||
|
@ -1213,37 +1272,39 @@ static PyObject *
|
||||||
unmarshal_code(PyObject *pathname, PyObject *data, time_t mtime)
|
unmarshal_code(PyObject *pathname, PyObject *data, time_t mtime)
|
||||||
{
|
{
|
||||||
PyObject *code;
|
PyObject *code;
|
||||||
char *buf = PyBytes_AsString(data);
|
unsigned char *buf = (unsigned char *)PyBytes_AsString(data);
|
||||||
Py_ssize_t size = PyBytes_Size(data);
|
Py_ssize_t size = PyBytes_Size(data);
|
||||||
|
|
||||||
if (size <= 9) {
|
if (size < 12) {
|
||||||
PyErr_SetString(ZipImportError,
|
PyErr_SetString(ZipImportError,
|
||||||
"bad pyc data");
|
"bad pyc data");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_long((unsigned char *)buf) != PyImport_GetMagicNumber()) {
|
if (get_uint32(buf) != (unsigned int)PyImport_GetMagicNumber()) {
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag) {
|
||||||
PySys_FormatStderr("# %R has bad magic\n",
|
PySys_FormatStderr("# %R has bad magic\n",
|
||||||
pathname);
|
pathname);
|
||||||
|
}
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None; /* signal caller to try alternative */
|
return Py_None; /* signal caller to try alternative */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mtime != 0 && !eq_mtime(get_long((unsigned char *)buf + 4),
|
if (mtime != 0 && !eq_mtime(get_uint32(buf + 4), mtime)) {
|
||||||
mtime)) {
|
if (Py_VerboseFlag) {
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# %R has bad mtime\n",
|
PySys_FormatStderr("# %R has bad mtime\n",
|
||||||
pathname);
|
pathname);
|
||||||
|
}
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None; /* signal caller to try alternative */
|
return Py_None; /* signal caller to try alternative */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX the pyc's size field is ignored; timestamp collisions are probably
|
/* XXX the pyc's size field is ignored; timestamp collisions are probably
|
||||||
unimportant with zip files. */
|
unimportant with zip files. */
|
||||||
code = PyMarshal_ReadObjectFromString(buf + 12, size - 12);
|
code = PyMarshal_ReadObjectFromString((char *)buf + 12, size - 12);
|
||||||
if (code == NULL)
|
if (code == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
if (!PyCode_Check(code)) {
|
if (!PyCode_Check(code)) {
|
||||||
Py_DECREF(code);
|
Py_DECREF(code);
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue