Check for off_t overflow.
diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c index 8cdd660..aba6402 100644 --- a/lib/zip_dirent.c +++ b/lib/zip_dirent.c
@@ -488,6 +488,13 @@ } } + if (!local) { + if (zde->offset > ZIP_OFF_MAX) { + _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return -1; + } + } + zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields); if (bufp)
diff --git a/lib/zip_extra_field.c b/lib/zip_extra_field.c index 9b9e399..d29cd76 100644 --- a/lib/zip_extra_field.c +++ b/lib/zip_extra_field.c
@@ -262,6 +262,7 @@ struct zip_extra_field *prev, *next; ef_head = prev = ef; + prev = NULL; while (ef) { if (ZIP_EF_IS_INTERNAL(ef->id)) { @@ -336,7 +337,6 @@ return 0; - /* XXX: check for off_t overflow */ if (fseeko(za->zp, (off_t)(e->orig->offset + 26), SEEK_SET) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1;
diff --git a/lib/zip_file_get_offset.c b/lib/zip_file_get_offset.c index 0bd1b10..a19e906 100644 --- a/lib/zip_file_get_offset.c +++ b/lib/zip_file_get_offset.c
@@ -58,7 +58,6 @@ offset = za->entry[idx].orig->offset; - /* XXX: check for off_t overflow */ if (fseeko(za->zp, (off_t)offset, SEEK_SET) != 0) { _zip_error_set(error, ZIP_ER_SEEK, errno); return 0;
diff --git a/lib/zip_open.c b/lib/zip_open.c index 807a5dd..8015e18 100644 --- a/lib/zip_open.c +++ b/lib/zip_open.c
@@ -216,7 +216,7 @@ cdp = eocd + 20; comment_len = _zip_read2(&cdp); - if (((zip_uint64_t)cd->offset)+cd->size > (zip_uint64_t)(buf_offset + (eocd-buf))) { + if ((zip_uint64_t)cd->offset+(zip_uint64_t)cd->size > (zip_uint64_t)buf_offset + (zip_uint64_t)(eocd-buf)) { /* cdir spans past EOCD record */ _zip_error_set(error, ZIP_ER_INCONS, 0); _zip_cdir_free(cd); @@ -259,7 +259,7 @@ } } - left = cd->size; + left = (zip_uint64_t)cd->size; i=0; while (i<cd->nentry && left > 0) { if ((cd->entry[i].orig=_zip_dirent_new()) == NULL @@ -317,7 +317,6 @@ return -1; } - /* XXX: check for off_t overflow */ if (fseeko(fp, (off_t)cd->entry[i].orig->offset, SEEK_SET) != 0) { _zip_error_set(error, ZIP_ER_SEEK, errno); return -1; @@ -368,8 +367,7 @@ if ((crc_should == UINT_MAX && errno != 0) || (end && *end)) return; - /* XXX: check off_t overflow */ - if (_zip_filerange_crc(za->zp, cdir->offset, (off_t)cdir->size, &crc_got, NULL) < 0) + if (_zip_filerange_crc(za->zp, cdir->offset, cdir->size, &crc_got, NULL) < 0) return; if (crc_got == crc_should) @@ -594,6 +592,11 @@ size = _zip_read4(&cdp); offset = _zip_read4(&cdp); + if (size > ZIP_OFF_MAX || offset > ZIP_OFF_MAX || offset+size > ZIP_OFF_MAX) { + _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; + } + if (offset+size > (zip_uint64_t)(buf_offset + (eocd-buf))) { /* cdir spans past EOCD record */ _zip_error_set(error, ZIP_ER_INCONS, 0); @@ -603,8 +606,7 @@ if ((cd=_zip_cdir_new(nentry, error)) == NULL) return NULL; - cd->size = size; - /* XXX: check for off_t overflow */ + cd->size = (off_t)size; cd->offset = (off_t)offset; return cd; @@ -687,7 +689,7 @@ size = _zip_read8(&cdp); offset = _zip_read8(&cdp); - if (size > ZIP_OFF_MAX || offset > ZIP_OFF_MAX) { + if (size > ZIP_OFF_MAX || offset > ZIP_OFF_MAX || offset+size > ZIP_OFF_MAX) { _zip_error_set(error, ZIP_ER_SEEK, EFBIG); return NULL; } @@ -700,7 +702,7 @@ return NULL; - cd->size = size; + cd->size = (off_t)size; cd->offset = (off_t)offset; return cd;
diff --git a/lib/zipint.h b/lib/zipint.h index 2477a59..8f03be0 100644 --- a/lib/zipint.h +++ b/lib/zipint.h
@@ -310,7 +310,7 @@ zip_uint64_t nentry; /* number of entries */ zip_uint64_t nentry_alloc; /* number of entries allocated */ - zip_uint64_t size; /* size of central directory */ + off_t size; /* size of central directory */ off_t offset; /* offset of central directory in file */ struct zip_string *comment; /* zip archive comment */ };