diff options
Diffstat (limited to 'Modules/zipimport.c')
-rw-r--r-- | Modules/zipimport.c | 511 |
1 files changed, 271 insertions, 240 deletions
diff --git a/Modules/zipimport.c b/Modules/zipimport.c index d8c3d8a..f822f92 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -49,7 +49,7 @@ static PyObject *zip_directory_cache = NULL; /* forward decls */ static PyObject *read_directory(PyObject *archive); static PyObject *get_data(PyObject *archive, PyObject *toc_entry); -static PyObject *get_module_code(ZipImporter *self, char *fullname, +static PyObject *get_module_code(ZipImporter *self, PyObject *fullname, int *p_ispackage, PyObject **p_modpath); @@ -63,109 +63,109 @@ static PyObject *get_module_code(ZipImporter *self, char *fullname, static int zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds) { - PyObject *pathobj, *files; - Py_UNICODE *path, *p, *prefix, buf[MAXPATHLEN+2]; - Py_ssize_t len; + PyObject *path, *files, *tmp; + PyObject *filename = NULL; + Py_ssize_t len, flen; +#ifdef ALTSEP + _Py_IDENTIFIER(replace); +#endif if (!_PyArg_NoKeywords("zipimporter()", kwds)) return -1; if (!PyArg_ParseTuple(args, "O&:zipimporter", - PyUnicode_FSDecoder, &pathobj)) + PyUnicode_FSDecoder, &path)) return -1; - /* copy path to buf */ - len = PyUnicode_GET_SIZE(pathobj); + if (PyUnicode_READY(path) == -1) + return -1; + + len = PyUnicode_GET_LENGTH(path); if (len == 0) { PyErr_SetString(ZipImportError, "archive path is empty"); goto error; } - if (len >= MAXPATHLEN) { - PyErr_SetString(ZipImportError, - "archive path too long"); - goto error; - } - Py_UNICODE_strcpy(buf, PyUnicode_AS_UNICODE(pathobj)); #ifdef ALTSEP - for (p = buf; *p; p++) { - if (*p == ALTSEP) - *p = SEP; - } + tmp = _PyObject_CallMethodId(path, &PyId_replace, "CC", ALTSEP, SEP); + if (!tmp) + goto error; + Py_DECREF(path); + path = tmp; #endif - path = NULL; - prefix = NULL; + filename = path; + Py_INCREF(filename); + flen = len; for (;;) { struct stat statbuf; int rv; - if (pathobj == NULL) { - pathobj = PyUnicode_FromUnicode(buf, len); - if (pathobj == NULL) - goto error; - } - rv = _Py_stat(pathobj, &statbuf); + rv = _Py_stat(filename, &statbuf); + if (rv == -2) + goto error; if (rv == 0) { /* it exists */ - if (S_ISREG(statbuf.st_mode)) - /* it's a file */ - path = buf; + if (!S_ISREG(statbuf.st_mode)) + /* it's a not file */ + Py_CLEAR(filename); break; } - else if (PyErr_Occurred()) - goto error; + Py_CLEAR(filename); /* back up one path element */ - p = Py_UNICODE_strrchr(buf, SEP); - if (prefix != NULL) - *prefix = SEP; - if (p == NULL) + flen = PyUnicode_FindChar(path, SEP, 0, flen, -1); + if (flen == -1) break; - *p = '\0'; - len = p - buf; - prefix = p; - Py_CLEAR(pathobj); + filename = PyUnicode_Substring(path, 0, flen); } - if (path == NULL) { + if (filename == NULL) { PyErr_SetString(ZipImportError, "not a Zip file"); goto error; } - files = PyDict_GetItem(zip_directory_cache, pathobj); + if (PyUnicode_READY(filename) < 0) + goto error; + + files = PyDict_GetItem(zip_directory_cache, filename); if (files == NULL) { - files = read_directory(pathobj); + files = read_directory(filename); if (files == NULL) goto error; - if (PyDict_SetItem(zip_directory_cache, pathobj, files) != 0) + if (PyDict_SetItem(zip_directory_cache, filename, files) != 0) goto error; } else Py_INCREF(files); self->files = files; - self->archive = pathobj; - pathobj = NULL; + /* Transfer reference */ + self->archive = filename; + filename = NULL; - if (prefix != NULL) { - prefix++; - len = Py_UNICODE_strlen(prefix); - if (prefix[len-1] != SEP) { + /* Check if there is a prefix directory following the filename. */ + if (flen != len) { + tmp = PyUnicode_Substring(path, flen+1, + PyUnicode_GET_LENGTH(path)); + if (tmp == NULL) + goto error; + self->prefix = tmp; + if (PyUnicode_READ_CHAR(path, len-1) != SEP) { /* add trailing SEP */ - prefix[len] = SEP; - prefix[len + 1] = '\0'; - len++; + tmp = PyUnicode_FromFormat("%U%c", self->prefix, SEP); + if (tmp == NULL) + goto error; + Py_DECREF(self->prefix); + self->prefix = tmp; } } else - len = 0; - self->prefix = PyUnicode_FromUnicode(prefix, len); - if (self->prefix == NULL) - goto error; - + self->prefix = PyUnicode_New(0, 0); + Py_DECREF(path); return 0; error: - Py_XDECREF(pathobj); + Py_DECREF(path); + Py_XDECREF(filename); return -1; } @@ -193,7 +193,7 @@ zipimporter_repr(ZipImporter *self) { if (self->archive == NULL) return PyUnicode_FromString("<zipimporter object \"???\">"); - else if (self->prefix != NULL && PyUnicode_GET_SIZE(self->prefix) != 0) + else if (self->prefix != NULL && PyUnicode_GET_LENGTH(self->prefix) != 0) return PyUnicode_FromFormat("<zipimporter object \"%U%c%U\">", self->archive, SEP, self->prefix); else @@ -202,49 +202,54 @@ zipimporter_repr(ZipImporter *self) } /* return fullname.split(".")[-1] */ -static char * -get_subname(char *fullname) +static PyObject * +get_subname(PyObject *fullname) { - char *subname = strrchr(fullname, '.'); - if (subname == NULL) - subname = fullname; - else - subname++; - return subname; + Py_ssize_t len, dot; + if (PyUnicode_READY(fullname) < 0) + return NULL; + len = PyUnicode_GET_LENGTH(fullname); + dot = PyUnicode_FindChar(fullname, '.', 0, len, -1); + if (dot == -1) { + Py_INCREF(fullname); + return fullname; + } else + return PyUnicode_Substring(fullname, dot+1, len); } /* Given a (sub)modulename, write the potential file path in the archive (without extension) to the path buffer. Return the - length of the resulting string. */ -static int -make_filename(PyObject *prefix_obj, char *name, char *path, size_t pathsize) -{ - size_t len; - char *p; - PyObject *prefix; + length of the resulting string. - prefix = PyUnicode_EncodeFSDefault(prefix_obj); - if (prefix == NULL) - return -1; - len = PyBytes_GET_SIZE(prefix); + return self.prefix + name.replace('.', os.sep) */ +static PyObject* +make_filename(PyObject *prefix, PyObject *name) +{ + PyObject *pathobj; + Py_UCS4 *p, *buf; + Py_ssize_t len; - /* self.prefix + name [+ SEP + "__init__"] + ".py[co]" */ - if (len + strlen(name) + 13 >= pathsize - 1) { - PyErr_SetString(ZipImportError, "path too long"); - Py_DECREF(prefix); - return -1; + len = PyUnicode_GET_LENGTH(prefix) + PyUnicode_GET_LENGTH(name) + 1; + p = buf = PyMem_Malloc(sizeof(Py_UCS4) * len); + if (buf == NULL) { + PyErr_NoMemory(); + return NULL; } - strcpy(path, PyBytes_AS_STRING(prefix)); - Py_DECREF(prefix); - strcpy(path + len, name); - for (p = path + len; *p; p++) { + if (!PyUnicode_AsUCS4(prefix, p, len, 0)) + return NULL; + p += PyUnicode_GET_LENGTH(prefix); + len -= PyUnicode_GET_LENGTH(prefix); + if (!PyUnicode_AsUCS4(name, p, len, 1)) + return NULL; + for (; *p; p++) { if (*p == '.') *p = SEP; } - len += strlen(name); - assert(len < INT_MAX); - return (int)len; + pathobj = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, + buf, p-buf); + PyMem_Free(buf); + return pathobj; } enum zi_module_info { @@ -256,27 +261,38 @@ enum zi_module_info { /* Return some information about a module. */ static enum zi_module_info -get_module_info(ZipImporter *self, char *fullname) +get_module_info(ZipImporter *self, PyObject *fullname) { - char *subname, path[MAXPATHLEN + 1]; - int len; + PyObject *subname; + PyObject *path, *fullpath, *item; struct st_zip_searchorder *zso; subname = get_subname(fullname); + if (subname == NULL) + return MI_ERROR; - len = make_filename(self->prefix, subname, path, sizeof(path)); - if (len < 0) + path = make_filename(self->prefix, subname); + Py_DECREF(subname); + if (path == NULL) return MI_ERROR; for (zso = zip_searchorder; *zso->suffix; zso++) { - strcpy(path + len, zso->suffix); - if (PyDict_GetItemString(self->files, path) != NULL) { + fullpath = PyUnicode_FromFormat("%U%s", path, zso->suffix); + if (fullpath == NULL) { + Py_DECREF(path); + return MI_ERROR; + } + item = PyDict_GetItem(self->files, fullpath); + Py_DECREF(fullpath); + if (item != NULL) { + Py_DECREF(path); if (zso->type & IS_PACKAGE) return MI_PACKAGE; else return MI_MODULE; } } + Py_DECREF(path); return MI_NOT_FOUND; } @@ -287,10 +303,10 @@ zipimporter_find_module(PyObject *obj, PyObject *args) { ZipImporter *self = (ZipImporter *)obj; PyObject *path = NULL; - char *fullname; + PyObject *fullname; enum zi_module_info mi; - if (!PyArg_ParseTuple(args, "s|O:zipimporter.find_module", + if (!PyArg_ParseTuple(args, "U|O:zipimporter.find_module", &fullname, &path)) return NULL; @@ -311,19 +327,21 @@ zipimporter_load_module(PyObject *obj, PyObject *args) { ZipImporter *self = (ZipImporter *)obj; PyObject *code = NULL, *mod, *dict; - char *fullname; - PyObject *modpath = NULL, *modpath_bytes; + PyObject *fullname; + PyObject *modpath = NULL; int ispackage; - if (!PyArg_ParseTuple(args, "s:zipimporter.load_module", + if (!PyArg_ParseTuple(args, "U:zipimporter.load_module", &fullname)) return NULL; + if (PyUnicode_READY(fullname) == -1) + return NULL; code = get_module_code(self, fullname, &ispackage, &modpath); if (code == NULL) goto error; - mod = PyImport_AddModule(fullname); + mod = PyImport_AddModuleObject(fullname); if (mod == NULL) goto error; dict = PyModule_GetDict(mod); @@ -336,17 +354,17 @@ zipimporter_load_module(PyObject *obj, PyObject *args) /* add __path__ to the module *before* the code gets executed */ PyObject *pkgpath, *fullpath; - char *subname = get_subname(fullname); + PyObject *subname = get_subname(fullname); int err; - fullpath = PyUnicode_FromFormat("%U%c%U%s", + fullpath = PyUnicode_FromFormat("%U%c%U%U", self->archive, SEP, self->prefix, subname); + Py_DECREF(subname); if (fullpath == NULL) goto error; - pkgpath = Py_BuildValue("[O]", fullpath); - Py_DECREF(fullpath); + pkgpath = Py_BuildValue("[N]", fullpath); if (pkgpath == NULL) goto error; err = PyDict_SetItemString(dict, "__path__", pkgpath); @@ -354,18 +372,13 @@ zipimporter_load_module(PyObject *obj, PyObject *args) if (err != 0) goto error; } - modpath_bytes = PyUnicode_EncodeFSDefault(modpath); - if (modpath_bytes == NULL) - goto error; - mod = PyImport_ExecCodeModuleEx(fullname, code, - PyBytes_AS_STRING(modpath_bytes)); - Py_DECREF(modpath_bytes); + mod = PyImport_ExecCodeModuleObject(fullname, code, modpath, NULL); Py_CLEAR(code); if (mod == NULL) goto error; if (Py_VerboseFlag) - PySys_FormatStderr("import %s # loaded from Zip %U\n", + PySys_FormatStderr("import %U # loaded from Zip %U\n", fullname, modpath); Py_DECREF(modpath); return mod; @@ -380,12 +393,10 @@ static PyObject * zipimporter_get_filename(PyObject *obj, PyObject *args) { ZipImporter *self = (ZipImporter *)obj; - PyObject *code; - char *fullname; - PyObject *modpath; + PyObject *fullname, *code, *modpath; int ispackage; - if (!PyArg_ParseTuple(args, "s:zipimporter.get_filename", + if (!PyArg_ParseTuple(args, "U:zipimporter.get_filename", &fullname)) return NULL; @@ -404,10 +415,10 @@ static PyObject * zipimporter_is_package(PyObject *obj, PyObject *args) { ZipImporter *self = (ZipImporter *)obj; - char *fullname; + PyObject *fullname; enum zi_module_info mi; - if (!PyArg_ParseTuple(args, "s:zipimporter.is_package", + if (!PyArg_ParseTuple(args, "U:zipimporter.is_package", &fullname)) return NULL; @@ -415,71 +426,70 @@ zipimporter_is_package(PyObject *obj, PyObject *args) if (mi == MI_ERROR) return NULL; if (mi == MI_NOT_FOUND) { - PyErr_Format(ZipImportError, "can't find module '%s'", fullname); + PyErr_Format(ZipImportError, "can't find module %R", fullname); return NULL; } return PyBool_FromLong(mi == MI_PACKAGE); } + static PyObject * zipimporter_get_data(PyObject *obj, PyObject *args) { ZipImporter *self = (ZipImporter *)obj; - PyObject *pathobj, *key; - const Py_UNICODE *path; + PyObject *path, *key; #ifdef ALTSEP - Py_UNICODE *p, buf[MAXPATHLEN + 1]; + _Py_IDENTIFIER(replace); #endif - Py_UNICODE *archive; PyObject *toc_entry; - Py_ssize_t path_len, len; + Py_ssize_t path_start, path_len, len; - if (!PyArg_ParseTuple(args, "U:zipimporter.get_data", &pathobj)) + if (!PyArg_ParseTuple(args, "U:zipimporter.get_data", &path)) return NULL; - path_len = PyUnicode_GET_SIZE(pathobj); - path = PyUnicode_AS_UNICODE(pathobj); #ifdef ALTSEP - if (path_len >= MAXPATHLEN) { - PyErr_SetString(ZipImportError, "path too long"); + path = _PyObject_CallMethodId(path, &PyId_replace, "CC", ALTSEP, SEP); + if (!path) return NULL; - } - Py_UNICODE_strcpy(buf, path); - for (p = buf; *p; p++) { - if (*p == ALTSEP) - *p = SEP; - } - path = buf; +#else + Py_INCREF(path); #endif - archive = PyUnicode_AS_UNICODE(self->archive); - len = PyUnicode_GET_SIZE(self->archive); - if ((size_t)len < Py_UNICODE_strlen(path) && - Py_UNICODE_strncmp(path, archive, len) == 0 && - path[len] == SEP) { - path += len + 1; - path_len -= len + 1; + if (PyUnicode_READY(path) == -1) + goto error; + + path_len = PyUnicode_GET_LENGTH(path); + + len = PyUnicode_GET_LENGTH(self->archive); + path_start = 0; + if (PyUnicode_Tailmatch(path, self->archive, 0, len, -1) + && PyUnicode_READ_CHAR(path, len) == SEP) { + path_start = len + 1; } - key = PyUnicode_FromUnicode(path, path_len); + key = PyUnicode_Substring(path, path_start, path_len); if (key == NULL) - return NULL; + goto error; toc_entry = PyDict_GetItem(self->files, key); if (toc_entry == NULL) { PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, key); Py_DECREF(key); - return NULL; + goto error; } Py_DECREF(key); + Py_DECREF(path); return get_data(self->archive, toc_entry); + error: + Py_DECREF(path); + return NULL; } static PyObject * zipimporter_get_code(PyObject *obj, PyObject *args) { ZipImporter *self = (ZipImporter *)obj; - char *fullname; + PyObject *fullname; - if (!PyArg_ParseTuple(args, "s:zipimporter.get_code", &fullname)) + if (!PyArg_ParseTuple(args, "U:zipimporter.get_code", &fullname)) return NULL; return get_module_code(self, fullname, NULL, NULL); @@ -490,34 +500,39 @@ zipimporter_get_source(PyObject *obj, PyObject *args) { ZipImporter *self = (ZipImporter *)obj; PyObject *toc_entry; - char *fullname, *subname, path[MAXPATHLEN+1]; - int len; + PyObject *fullname, *subname, *path, *fullpath; enum zi_module_info mi; - if (!PyArg_ParseTuple(args, "s:zipimporter.get_source", &fullname)) + if (!PyArg_ParseTuple(args, "U:zipimporter.get_source", &fullname)) return NULL; mi = get_module_info(self, fullname); if (mi == MI_ERROR) return NULL; if (mi == MI_NOT_FOUND) { - PyErr_Format(ZipImportError, "can't find module '%s'", fullname); + PyErr_Format(ZipImportError, "can't find module %R", fullname); return NULL; } + subname = get_subname(fullname); + if (subname == NULL) + return NULL; - len = make_filename(self->prefix, subname, path, sizeof(path)); - if (len < 0) + path = make_filename(self->prefix, subname); + Py_DECREF(subname); + if (path == NULL) return NULL; - if (mi == MI_PACKAGE) { - path[len] = SEP; - strcpy(path + len + 1, "__init__.py"); - } + if (mi == MI_PACKAGE) + fullpath = PyUnicode_FromFormat("%U%c__init__.py", path, SEP); else - strcpy(path + len, ".py"); + fullpath = PyUnicode_FromFormat("%U.py", path); + Py_DECREF(path); + if (fullpath == NULL) + return NULL; - toc_entry = PyDict_GetItemString(self->files, path); + toc_entry = PyDict_GetItem(self->files, fullpath); + Py_DECREF(fullpath); if (toc_entry != NULL) { PyObject *res, *bytes; bytes = get_data(self->archive, toc_entry); @@ -708,50 +723,41 @@ get_long(unsigned char *buf) { data_size and file_offset are 0. */ static PyObject * -read_directory(PyObject *archive_obj) +read_directory(PyObject *archive) { - /* FIXME: work on Py_UNICODE* instead of char* */ PyObject *files = NULL; FILE *fp; unsigned short flags; short compress, time, date, name_size; long crc, data_size, file_size, header_size; Py_ssize_t file_offset, header_position, header_offset; - long i, l, count; - size_t length; - Py_UNICODE path[MAXPATHLEN + 5]; + long l, count; + Py_ssize_t i; char name[MAXPATHLEN + 5]; PyObject *nameobj = NULL; char *p, endof_central_dir[22]; Py_ssize_t arc_offset; /* Absolute offset to start of the zip-archive. */ - PyObject *pathobj; + PyObject *path; const char *charset; int bootstrap; - if (PyUnicode_GET_SIZE(archive_obj) > MAXPATHLEN) { - PyErr_SetString(PyExc_OverflowError, - "Zip path name is too long"); - return NULL; - } - Py_UNICODE_strcpy(path, PyUnicode_AS_UNICODE(archive_obj)); - - fp = _Py_fopen(archive_obj, "rb"); + fp = _Py_fopen(archive, "rb"); if (fp == NULL) { if (!PyErr_Occurred()) - PyErr_Format(ZipImportError, "can't open Zip file: '%U'", archive_obj); + PyErr_Format(ZipImportError, "can't open Zip file: %R", archive); return NULL; } fseek(fp, -22, SEEK_END); header_position = ftell(fp); if (fread(endof_central_dir, 1, 22, fp) != 22) { fclose(fp); - PyErr_Format(ZipImportError, "can't read Zip file: '%U'", archive_obj); + PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) { /* Bad: End of Central Dir signature */ fclose(fp); - PyErr_Format(ZipImportError, "not a Zip file: '%U'", archive_obj); + PyErr_Format(ZipImportError, "not a Zip file: %R", archive); return NULL; } @@ -764,9 +770,6 @@ read_directory(PyObject *archive_obj) if (files == NULL) goto error; - length = Py_UNICODE_strlen(path); - path[length] = SEP; - /* Start of Central Directory */ count = 0; for (;;) { @@ -795,7 +798,7 @@ read_directory(PyObject *archive_obj) name_size = MAXPATHLEN; p = name; - for (i = 0; i < name_size; i++) { + for (i = 0; i < (Py_ssize_t)name_size; i++) { *p = (char)getc(fp); if (*p == '/') *p = SEP; @@ -820,6 +823,8 @@ read_directory(PyObject *archive_obj) else charset = "cp437"; nameobj = PyUnicode_Decode(name, name_size, charset, NULL); + if (PyUnicode_READY(nameobj) == -1) + goto error; if (nameobj == NULL) { if (bootstrap) PyErr_Format(PyExc_NotImplementedError, @@ -828,12 +833,10 @@ read_directory(PyObject *archive_obj) PY_MAJOR_VERSION, PY_MINOR_VERSION); goto error; } - Py_UNICODE_strncpy(path + length + 1, PyUnicode_AS_UNICODE(nameobj), MAXPATHLEN - length - 1); - - pathobj = PyUnicode_FromUnicode(path, Py_UNICODE_strlen(path)); - if (pathobj == NULL) + path = PyUnicode_FromFormat("%U%c%U", archive, SEP, nameobj); + if (path == NULL) goto error; - t = Py_BuildValue("Nhllnhhl", pathobj, compress, data_size, + t = Py_BuildValue("Nhllnhhl", path, compress, data_size, file_size, file_offset, time, date, crc); if (t == NULL) goto error; @@ -846,8 +849,8 @@ read_directory(PyObject *archive_obj) } fclose(fp); if (Py_VerboseFlag) - PySys_FormatStderr("# zipimport: found %ld names in %U\n", - count, archive_obj); + PySys_FormatStderr("# zipimport: found %ld names in %R\n", + count, archive); return files; error: fclose(fp); @@ -865,6 +868,7 @@ get_decompress_func(void) static int importing_zlib = 0; PyObject *zlib; PyObject *decompress; + _Py_IDENTIFIER(decompress); if (importing_zlib != 0) /* Someone has a zlib.py[co] in their Zip file; @@ -874,8 +878,8 @@ get_decompress_func(void) zlib = PyImport_ImportModuleNoBlock("zlib"); importing_zlib = 0; if (zlib != NULL) { - decompress = PyObject_GetAttrString(zlib, - "decompress"); + decompress = _PyObject_GetAttrId(zlib, + &PyId_decompress); Py_DECREF(zlib); } else { @@ -1001,7 +1005,7 @@ eq_mtime(time_t t1, time_t t2) to .py if available and we don't want to mask other errors). Returns a new reference. */ static PyObject * -unmarshal_code(char *pathname, PyObject *data, time_t mtime) +unmarshal_code(PyObject *pathname, PyObject *data, time_t mtime) { PyObject *code; char *buf = PyBytes_AsString(data); @@ -1015,8 +1019,8 @@ unmarshal_code(char *pathname, PyObject *data, time_t mtime) if (get_long((unsigned char *)buf) != PyImport_GetMagicNumber()) { if (Py_VerboseFlag) - PySys_WriteStderr("# %s has bad magic\n", - pathname); + PySys_FormatStderr("# %R has bad magic\n", + pathname); Py_INCREF(Py_None); return Py_None; /* signal caller to try alternative */ } @@ -1024,19 +1028,21 @@ unmarshal_code(char *pathname, PyObject *data, time_t mtime) if (mtime != 0 && !eq_mtime(get_long((unsigned char *)buf + 4), mtime)) { if (Py_VerboseFlag) - PySys_WriteStderr("# %s has bad mtime\n", - pathname); + PySys_FormatStderr("# %R has bad mtime\n", + pathname); Py_INCREF(Py_None); return Py_None; /* signal caller to try alternative */ } - code = PyMarshal_ReadObjectFromString(buf + 8, size - 8); + /* XXX the pyc's size field is ignored; timestamp collisions are probably + unimportant with zip files. */ + code = PyMarshal_ReadObjectFromString(buf + 12, size - 12); if (code == NULL) return NULL; if (!PyCode_Check(code)) { Py_DECREF(code); PyErr_Format(PyExc_TypeError, - "compiled module %s is not a code object", + "compiled module %R is not a code object", pathname); return NULL; } @@ -1050,11 +1056,12 @@ unmarshal_code(char *pathname, PyObject *data, time_t mtime) static PyObject * normalize_line_endings(PyObject *source) { - char *buf, *q, *p = PyBytes_AsString(source); + char *buf, *q, *p; PyObject *fixed_source; int len = 0; - if (!p) { + p = PyBytes_AsString(source); + if (p == NULL) { return PyBytes_FromStringAndSize("\n\0", 2); } @@ -1087,16 +1094,24 @@ normalize_line_endings(PyObject *source) /* Given a string buffer containing Python source code, compile it return and return a code object as a new reference. */ static PyObject * -compile_source(char *pathname, PyObject *source) +compile_source(PyObject *pathname, PyObject *source) { - PyObject *code, *fixed_source; + PyObject *code, *fixed_source, *pathbytes; + + pathbytes = PyUnicode_EncodeFSDefault(pathname); + if (pathbytes == NULL) + return NULL; fixed_source = normalize_line_endings(source); - if (fixed_source == NULL) + if (fixed_source == NULL) { + Py_DECREF(pathbytes); return NULL; + } - code = Py_CompileString(PyBytes_AsString(fixed_source), pathname, + code = Py_CompileString(PyBytes_AsString(fixed_source), + PyBytes_AsString(pathbytes), Py_file_input); + Py_DECREF(pathbytes); Py_DECREF(fixed_source); return code; } @@ -1125,14 +1140,22 @@ parse_dostime(int dostime, int dosdate) modification time of the matching .py file, or 0 if no source is available. */ static time_t -get_mtime_of_source(ZipImporter *self, char *path) +get_mtime_of_source(ZipImporter *self, PyObject *path) { - PyObject *toc_entry; - time_t mtime = 0; - Py_ssize_t lastchar = strlen(path) - 1; - char savechar = path[lastchar]; - path[lastchar] = '\0'; /* strip 'c' or 'o' from *.py[co] */ - toc_entry = PyDict_GetItemString(self->files, path); + PyObject *toc_entry, *stripped; + time_t mtime; + + /* strip 'c' or 'o' from *.py[co] */ + if (PyUnicode_READY(path) == -1) + return (time_t)-1; + stripped = PyUnicode_FromKindAndData(PyUnicode_KIND(path), + PyUnicode_DATA(path), + PyUnicode_GET_LENGTH(path) - 1); + if (stripped == NULL) + return (time_t)-1; + + toc_entry = PyDict_GetItem(self->files, stripped); + Py_DECREF(stripped); if (toc_entry != NULL && PyTuple_Check(toc_entry) && PyTuple_Size(toc_entry) == 8) { /* fetch the time stamp of the .py file for comparison @@ -1141,8 +1164,8 @@ get_mtime_of_source(ZipImporter *self, char *path) time = PyLong_AsLong(PyTuple_GetItem(toc_entry, 5)); date = PyLong_AsLong(PyTuple_GetItem(toc_entry, 6)); mtime = parse_dostime(time, date); - } - path[lastchar] = savechar; + } else + mtime = 0; return mtime; } @@ -1152,24 +1175,17 @@ static PyObject * get_code_from_data(ZipImporter *self, int ispackage, int isbytecode, time_t mtime, PyObject *toc_entry) { - PyObject *data, *code; - PyObject *modpath; + PyObject *data, *modpath, *code; data = get_data(self->archive, toc_entry); if (data == NULL) return NULL; - modpath = PyUnicode_EncodeFSDefault(PyTuple_GetItem(toc_entry, 0)); - if (modpath == NULL) { - Py_DECREF(data); - return NULL; - } - + modpath = PyTuple_GetItem(toc_entry, 0); if (isbytecode) - code = unmarshal_code(PyBytes_AS_STRING(modpath), data, mtime); + code = unmarshal_code(modpath, data, mtime); else - code = compile_source(PyBytes_AS_STRING(modpath), data); - Py_DECREF(modpath); + code = compile_source(modpath, data); Py_DECREF(data); return code; } @@ -1177,35 +1193,45 @@ get_code_from_data(ZipImporter *self, int ispackage, int isbytecode, /* Get the code object associated with the module specified by 'fullname'. */ static PyObject * -get_module_code(ZipImporter *self, char *fullname, +get_module_code(ZipImporter *self, PyObject *fullname, int *p_ispackage, PyObject **p_modpath) { - PyObject *toc_entry; - char *subname, path[MAXPATHLEN + 1]; - int len; + PyObject *code = NULL, *toc_entry, *subname; + PyObject *path, *fullpath = NULL; struct st_zip_searchorder *zso; subname = get_subname(fullname); + if (subname == NULL) + return NULL; - len = make_filename(self->prefix, subname, path, sizeof(path)); - if (len < 0) + path = make_filename(self->prefix, subname); + Py_DECREF(subname); + if (path == NULL) return NULL; for (zso = zip_searchorder; *zso->suffix; zso++) { - PyObject *code = NULL; + code = NULL; + + fullpath = PyUnicode_FromFormat("%U%s", path, zso->suffix); + if (fullpath == NULL) + goto exit; - strcpy(path + len, zso->suffix); if (Py_VerboseFlag > 1) - PySys_FormatStderr("# trying %U%c%s\n", - self->archive, (int)SEP, path); - toc_entry = PyDict_GetItemString(self->files, path); + PySys_FormatStderr("# trying %U%c%U\n", + self->archive, (int)SEP, fullpath); + toc_entry = PyDict_GetItem(self->files, fullpath); if (toc_entry != NULL) { time_t mtime = 0; int ispackage = zso->type & IS_PACKAGE; int isbytecode = zso->type & IS_BYTECODE; - if (isbytecode) - mtime = get_mtime_of_source(self, path); + if (isbytecode) { + mtime = get_mtime_of_source(self, fullpath); + if (mtime == (time_t)-1 && PyErr_Occurred()) { + goto exit; + } + } + Py_CLEAR(fullpath); if (p_ispackage != NULL) *p_ispackage = ispackage; code = get_code_from_data(self, ispackage, @@ -1221,11 +1247,16 @@ get_module_code(ZipImporter *self, char *fullname, *p_modpath = PyTuple_GetItem(toc_entry, 0); Py_INCREF(*p_modpath); } - return code; + goto exit; } + else + Py_CLEAR(fullpath); } - PyErr_Format(ZipImportError, "can't find module '%s'", fullname); - return NULL; + PyErr_Format(ZipImportError, "can't find module %R", fullname); +exit: + Py_DECREF(path); + Py_XDECREF(fullpath); + return code; } |