From 67acdd2c096e2b3678df93b24bb735b5d450af09 Mon Sep 17 00:00:00 2001 From: Pierre Joye Date: Mon, 1 Feb 2010 20:56:03 +0000 Subject: [PATCH] - update to 0.9.3 --- ext/zip/lib/zip_close.c | 43 ++++++------ ext/zip/lib/zip_dirent.c | 96 ++++++++++++++++++--------- ext/zip/lib/zip_fclose.c | 14 ++-- ext/zip/lib/zip_file_get_offset.c | 2 +- ext/zip/lib/zip_fread.c | 31 ++++----- ext/zip/lib/zip_get_archive_comment.c | 10 +-- ext/zip/lib/zip_open.c | 24 +++++-- ext/zip/lib/zipint.h | 1 + 8 files changed, 132 insertions(+), 89 deletions(-) diff --git a/ext/zip/lib/zip_close.c b/ext/zip/lib/zip_close.c index dec8f5b70bc..0796f27462b 100644 --- a/ext/zip/lib/zip_close.c +++ b/ext/zip/lib/zip_close.c @@ -193,7 +193,8 @@ zip_close(struct zip *za) error = 1; break; } - if (_zip_dirent_read(&de, za->zp, NULL, 0, 1, &za->error) != 0) { + if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1, + &za->error) != 0) { error = 1; break; } @@ -233,11 +234,10 @@ zip_close(struct zip *za) zs = NULL; if (!ZIP_ENTRY_DATA_CHANGED(za->entry+i)) { - if ((zs=zip_source_zip(za, za, i, ZIP_FL_RECOMPRESS, 0, -1)) - == NULL) { - error = 1; - break; - } + if ((zs=zip_source_zip(za, za, i, ZIP_FL_RECOMPRESS, 0, -1)) == NULL) { + error = 1; + break; + } } if (add_data(za, zs ? zs : za->entry[i].source, &de, out) < 0) { @@ -266,6 +266,8 @@ zip_close(struct zip *za) _zip_dirent_finalize(&de); } + free(filelist); + if (!error) { if (write_cdir(za, cd, out) < 0) error = 1; @@ -290,27 +292,29 @@ zip_close(struct zip *za) return -1; } - if (za->zp) { - fclose(za->zp); - za->zp = NULL; - reopen_on_error = 1; + if (za->zp) { + fclose(za->zp); + za->zp = NULL; + reopen_on_error = 1; } if (_zip_rename(temp, za->zn) != 0) { - _zip_error_set(&za->error, ZIP_ER_RENAME, errno); - remove(temp); - free(temp); - if (reopen_on_error) { - /* ignore errors, since we're already in an error case */ - za->zp = fopen(za->zn, "rb"); + _zip_error_set(&za->error, ZIP_ER_RENAME, errno); + remove(temp); + free(temp); + if (reopen_on_error) { + /* ignore errors, since we're already in an error case */ + za->zp = fopen(za->zn, "rb"); + } + return -1; } - return -1; - } mask = umask(0); umask(mask); chmod(za->zn, 0666&~mask); + if (za->ch_comment) + free(za->ch_comment); _zip_free(za); - free(temp); + free(temp); return 0; } @@ -445,6 +449,7 @@ add_data_uncomp(struct zip *za, zip_source_callback cb, void *ud, zstr.next_out = (Bytef *)b2; zstr.avail_out = sizeof(b2); + zstr.next_in = NULL; zstr.avail_in = 0; flush = 0; diff --git a/ext/zip/lib/zip_dirent.c b/ext/zip/lib/zip_dirent.c index 425f7ff9225..39fcb6f62d6 100644 --- a/ext/zip/lib/zip_dirent.c +++ b/ext/zip/lib/zip_dirent.c @@ -68,6 +68,30 @@ _zip_cdir_free(struct zip_cdir *cd) +int +_zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error) +{ + struct zip_dirent *entry; + + if (nentry < cd->nentry) { + _zip_error_set(error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((entry=((struct zip_dirent *) + realloc(cd->entry, sizeof(*(cd->entry))*nentry))) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + + cd->nentry = nentry; + cd->entry = entry; + + return 0; +} + + + struct zip_cdir * _zip_cdir_new(int nentry, struct zip_error *error) { @@ -173,19 +197,23 @@ _zip_dirent_init(struct zip_dirent *de) Fills the zip directory entry zde. If bufp is non-NULL, data is taken from there and bufp is advanced - by the amount of data used; no more than left bytes are used. - Otherwise data is read from fp as needed. + by the amount of data used; otherwise data is read from fp as needed. + + if leftp is non-NULL, no more bytes than specified by it are used, + and *leftp is reduced by the number of bytes used. - If localp != 0, it reads a local header instead of a central + If local != 0, it reads a local header instead of a central directory entry. Returns 0 if successful. On error, error is filled in and -1 is returned. + + XXX: leftp and file position undefined on error. */ int _zip_dirent_read(struct zip_dirent *zde, FILE *fp, - unsigned char **bufp, unsigned int left, int localp, + unsigned char **bufp, unsigned int *leftp, int local, struct zip_error *error) { unsigned char buf[CDENTRYSIZE]; @@ -193,18 +221,19 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp, unsigned short dostime, dosdate; unsigned int size; - if (localp) + if (local) size = LENTRYSIZE; else size = CDENTRYSIZE; - + + if (leftp && (*leftp < size)) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + if (bufp) { /* use data from buffer */ cur = *bufp; - if (left < size) { - _zip_error_set(error, ZIP_ER_NOZIP, 0); - return -1; - } } else { /* read entry from disk */ @@ -212,11 +241,10 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp, _zip_error_set(error, ZIP_ER_READ, errno); return -1; } - left = size; cur = buf; } - if (memcmp(cur, (localp ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) { + if (memcmp(cur, (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) { _zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } @@ -225,7 +253,7 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp, /* convert buffercontents to zip_dirent */ - if (!localp) + if (!local) zde->version_madeby = _zip_read2(&cur); else zde->version_madeby = 0; @@ -245,7 +273,7 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp, zde->filename_len = _zip_read2(&cur); zde->extrafield_len = _zip_read2(&cur); - if (localp) { + if (local) { zde->comment_len = 0; zde->disk_number = 0; zde->int_attrib = 0; @@ -263,13 +291,14 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp, zde->extrafield = NULL; zde->comment = NULL; - if (bufp) { - if (left < CDENTRYSIZE + (zde->filename_len+zde->extrafield_len - +zde->comment_len)) { - _zip_error_set(error, ZIP_ER_NOZIP, 0); - return -1; - } + size += zde->filename_len+zde->extrafield_len+zde->comment_len; + if (leftp && (*leftp < size)) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + if (bufp) { if (zde->filename_len) { zde->filename = _zip_readstr(&cur, zde->filename_len, 1, error); if (!zde->filename) @@ -312,6 +341,8 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp, if (bufp) *bufp = cur; + if (leftp) + *leftp -= size; return 0; } @@ -442,23 +473,22 @@ _zip_dirent_write(struct zip_dirent *zde, FILE *fp, int localp, static time_t _zip_d2u_time(int dtime, int ddate) { - struct tm *tm; - time_t now; + struct tm tm; - now = time(NULL); - tm = localtime(&now); - /* let mktime decide if DST is in effect */ - tm->tm_isdst = -1; + memset(&tm, sizeof(tm), 0); - tm->tm_year = ((ddate>>9)&127) + 1980 - 1900; - tm->tm_mon = ((ddate>>5)&15) - 1; - tm->tm_mday = ddate&31; + /* let mktime decide if DST is in effect */ + tm.tm_isdst = -1; + + tm.tm_year = ((ddate>>9)&127) + 1980 - 1900; + tm.tm_mon = ((ddate>>5)&15) - 1; + tm.tm_mday = ddate&31; - tm->tm_hour = (dtime>>11)&31; - tm->tm_min = (dtime>>5)&63; - tm->tm_sec = (dtime<<1)&62; + tm.tm_hour = (dtime>>11)&31; + tm.tm_min = (dtime>>5)&63; + tm.tm_sec = (dtime<<1)&62; - return mktime(tm); + return mktime(&tm); } diff --git a/ext/zip/lib/zip_fclose.c b/ext/zip/lib/zip_fclose.c index 6bf697301ae..8f062d9d090 100644 --- a/ext/zip/lib/zip_fclose.c +++ b/ext/zip/lib/zip_fclose.c @@ -49,13 +49,13 @@ zip_fclose(struct zip_file *zf) free(zf->buffer); free(zf->zstr); if (zf->za) { - for (i=0; iza->nfile; i++) { - if (zf->za->file[i] == zf) { - zf->za->file[i] = zf->za->file[zf->za->nfile-1]; - zf->za->nfile--; - break; - } - } + for (i=0; iza->nfile; i++) { + if (zf->za->file[i] == zf) { + zf->za->file[i] = zf->za->file[zf->za->nfile-1]; + zf->za->nfile--; + break; + } + } } ret = 0; diff --git a/ext/zip/lib/zip_file_get_offset.c b/ext/zip/lib/zip_file_get_offset.c index 68f92f1fe61..b96fd5e4809 100644 --- a/ext/zip/lib/zip_file_get_offset.c +++ b/ext/zip/lib/zip_file_get_offset.c @@ -63,7 +63,7 @@ _zip_file_get_offset(struct zip *za, int idx) return 0; } - if (_zip_dirent_read(&de, za->zp, NULL, 0, 1, &za->error) != 0) + if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1, &za->error) != 0) return 0; offset += LENTRYSIZE + de.filename_len + de.extrafield_len; diff --git a/ext/zip/lib/zip_fread.c b/ext/zip/lib/zip_fread.c index 57c5208a6b4..00a6bdc4e05 100644 --- a/ext/zip/lib/zip_fread.c +++ b/ext/zip/lib/zip_fread.c @@ -41,7 +41,7 @@ ZIP_EXTERN(ssize_t) zip_fread(struct zip_file *zf, void *outbuf, size_t toread) { int ret; - size_t out_before, len; + size_t out_before, len; int i; if (!zf) @@ -63,7 +63,7 @@ zip_fread(struct zip_file *zf, void *outbuf, size_t toread) } return 0; } - + if ((zf->flags & ZIP_ZF_DECOMP) == 0) { ret = _zip_file_fillbuf(outbuf, toread, zf); if (ret > 0) { @@ -84,25 +84,22 @@ zip_fread(struct zip_file *zf, void *outbuf, size_t toread) switch (ret) { case Z_STREAM_END: - zf->flags |= ZIP_ZF_EOF; + if (zf->zstr->total_out == out_before) { + if (zf->crc != zf->crc_orig) { + _zip_error_set(&zf->error, ZIP_ER_CRC, 0); + return -1; + } + else + return 0; + } + + /* fallthrough */ case Z_OK: - - /* all ok */ - /* Z_STREAM_END probably won't happen, since we didn't - have a header */ len = zf->zstr->total_out - out_before; if (len >= zf->bytes_left || len >= toread) { - if (zf->flags & ZIP_ZF_CRC) { - zf->crc = crc32(zf->crc, (Bytef *)outbuf, len); - if ((zf->flags & ZIP_ZF_EOF) == 1) { - if (zf->crc != zf->crc_orig) { - _zip_error_set(&zf->error, ZIP_ER_CRC, 0); - return -1; - } - - } - } + if (zf->flags & ZIP_ZF_CRC) + zf->crc = crc32(zf->crc, (Bytef *)outbuf, len); zf->bytes_left -= len; return len; } diff --git a/ext/zip/lib/zip_get_archive_comment.c b/ext/zip/lib/zip_get_archive_comment.c index fe97e6e8c18..ed1324fd5b9 100644 --- a/ext/zip/lib/zip_get_archive_comment.c +++ b/ext/zip/lib/zip_get_archive_comment.c @@ -42,11 +42,11 @@ zip_get_archive_comment(struct zip *za, int *lenp, int flags) { if ((flags & ZIP_FL_UNCHANGED) || (za->ch_comment_len == -1)) { - if (za->cdir) { - if (lenp != NULL) - *lenp = za->cdir->comment_len; - return za->cdir->comment; - } + if (za->cdir) { + if (lenp != NULL) + *lenp = za->cdir->comment_len; + return za->cdir->comment; + } else { if (lenp != NULL) *lenp = -1; diff --git a/ext/zip/lib/zip_open.c b/ext/zip/lib/zip_open.c index dbab6ec4afc..31e12f4fc5f 100644 --- a/ext/zip/lib/zip_open.c +++ b/ext/zip/lib/zip_open.c @@ -75,9 +75,10 @@ zip_open(const char *fn, int flags, int *zep) if (!(flags & ZIP_OVERWRITE)) { return NULL; } - + case 0: return _zip_allocate_new(fn, zep); + default: break; } @@ -161,6 +162,7 @@ _zip_readcdir(FILE *fp, unsigned char *buf, unsigned char *eocd, int buflen, struct zip_cdir *cd; unsigned char *cdp, **bufp; int i, comlen, nentry; + unsigned int left; comlen = buf + buflen - eocd - EOCDLEN; if (comlen < 0) { @@ -214,7 +216,6 @@ _zip_readcdir(FILE *fp, unsigned char *buf, unsigned char *eocd, int buflen, } } - cdp = eocd; if (cd->size < (unsigned int)(eocd-buf)) { /* if buffer already read in, use it */ cdp = eocd - cd->size; @@ -238,14 +239,23 @@ _zip_readcdir(FILE *fp, unsigned char *buf, unsigned char *eocd, int buflen, } } - for (i=0; inentry; i++) { - if ((_zip_dirent_read(cd->entry+i, fp, bufp, eocd-cdp, 0, - error)) < 0) { + left = cd->size; + i=0; + do { + if (i == cd->nentry && left > 0) { + /* Infozip extension for more than 64k entries: + nentries wraps around, size indicates correct EOCD */ + _zip_cdir_grow(cd, cd->nentry+0x10000, error); + } + + if ((_zip_dirent_read(cd->entry+i, fp, bufp, &left, 0, error)) < 0) { cd->nentry = i; _zip_cdir_free(cd); return NULL; } - } + i++; + + } while (inentry); return cd; } @@ -294,7 +304,7 @@ _zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error) return -1; } - if (_zip_dirent_read(&temp, fp, NULL, 0, 1, error) == -1) + if (_zip_dirent_read(&temp, fp, NULL, NULL, 1, error) == -1) return -1; if (_zip_headercomp(cd->entry+i, 0, &temp, 1) != 0) { diff --git a/ext/zip/lib/zipint.h b/ext/zip/lib/zipint.h index e7e35e4dd7b..f1514c5b6ae 100644 --- a/ext/zip/lib/zipint.h +++ b/ext/zip/lib/zipint.h @@ -213,6 +213,7 @@ extern const int _zip_err_type[]; int _zip_cdir_compute_crc(struct zip *, uLong *); void _zip_cdir_free(struct zip_cdir *); +int _zip_cdir_grow(struct zip_cdir *, int, struct zip_error *); struct zip_cdir *_zip_cdir_new(int, struct zip_error *); int _zip_cdir_write(struct zip_cdir *, FILE *, struct zip_error *);