static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) { zip_uint64_t i; zip_uint64_t min, max, j; struct zip_dirent temp; _zip_dirent_init(&temp); if (cd->nentry) { max = cd->entry[0].orig->offset; min = cd->entry[0].orig->offset; } else min = max = 0; for (i=0; i<cd->nentry; i++) { if (cd->entry[i].orig->offset < min) min = cd->entry[i].orig->offset; if (min > (zip_uint64_t)cd->offset) { zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE; if (j > max) max = j; if (max > (zip_uint64_t)cd->offset) { zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) { _zip_error_set_from_source(error, za->src); return -1; } if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) { _zip_dirent_finalize(&temp); return -1; } if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) { zip_error_set(error, ZIP_ER_INCONS, 0); _zip_dirent_finalize(&temp); return -1; } cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields); cd->entry[i].orig->local_extra_fields_read = 1; temp.extra_fields = NULL; _zip_dirent_finalize(&temp); } return (max-min) < ZIP_INT64_MAX ? (zip_int64_t)(max-min) : ZIP_INT64_MAX; }
static zip_int64_t _zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error) { zip_uint64_t i; zip_uint64_t min, max, j; struct zip_dirent temp; if (cd->nentry) { max = cd->entry[0].orig->offset; min = cd->entry[0].orig->offset; } else min = max = 0; for (i=0; i<cd->nentry; i++) { if (cd->entry[i].orig->offset < min) min = cd->entry[i].orig->offset; if (min > (zip_uint64_t)cd->offset) { _zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE; if (j > max) max = j; if (max > (zip_uint64_t)cd->offset) { _zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } if (fseeko(fp, (off_t)cd->entry[i].orig->offset, SEEK_SET) != 0) { _zip_error_set(error, ZIP_ER_SEEK, errno); return -1; } if (_zip_dirent_read(&temp, fp, NULL, NULL, 1, error) == -1) return -1; if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) { _zip_error_set(error, ZIP_ER_INCONS, 0); _zip_dirent_finalize(&temp); return -1; } cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields); cd->entry[i].orig->local_extra_fields_read = 1; temp.extra_fields = NULL; _zip_dirent_finalize(&temp); } return (max-min) < ZIP_INT64_MAX ? (zip_int64_t)(max-min) : ZIP_INT64_MAX; }
int _zip_read_local_ef(struct zip *za, zip_uint64_t idx) { struct zip_entry *e; unsigned char b[4]; const unsigned char *p; zip_uint16_t fname_len, ef_len; if (idx >= za->nentry) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } e = za->entry+idx; if (e->orig == NULL || e->orig->local_extra_fields_read) return 0; if (fseeko(za->zp, (off_t)(e->orig->offset + 26), SEEK_SET) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } if (fread(b, sizeof(b), 1, za->zp) != 1) { _zip_error_set(&za->error, ZIP_ER_READ, errno); return -1; } p = b; fname_len = _zip_read2(&p); ef_len = _zip_read2(&p); if (ef_len > 0) { struct zip_extra_field *ef; zip_uint8_t *ef_raw; if (fseek(za->zp, fname_len, SEEK_CUR) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } ef_raw = _zip_read_data(NULL, za->zp, ef_len, 0, &za->error); if (ef_raw == NULL) return -1; if ((ef=_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &za->error)) == NULL) { free(ef_raw); return -1; } free(ef_raw); ef = _zip_ef_remove_internal(ef); e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); } e->orig->local_extra_fields_read = 1; if (e->changes && e->changes->local_extra_fields_read == 0) { e->changes->extra_fields = e->orig->extra_fields; e->changes->local_extra_fields_read = 1; } return 0; }
int _zip_read_local_ef(zip_t *za, zip_uint64_t idx) { zip_entry_t *e; unsigned char b[4]; zip_buffer_t *buffer; zip_uint16_t fname_len, ef_len; if (idx >= za->nentry) { zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } e = za->entry+idx; if (e->orig == NULL || e->orig->local_extra_fields_read) return 0; if (e->orig->offset + 26 > ZIP_INT64_MAX) { zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG); return -1; } if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) { _zip_error_set_from_source(&za->error, za->src); return -1; } if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) { return -1; } fname_len = _zip_buffer_get_16(buffer); ef_len = _zip_buffer_get_16(buffer); if (!_zip_buffer_eof(buffer)) { _zip_buffer_free(buffer); zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); return -1; } _zip_buffer_free(buffer); if (ef_len > 0) { zip_extra_field_t *ef; zip_uint8_t *ef_raw; if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) { zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error); if (ef_raw == NULL) return -1; if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) { free(ef_raw); return -1; } free(ef_raw); if (ef) { ef = _zip_ef_remove_internal(ef); e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); } } e->orig->local_extra_fields_read = 1; if (e->changes && e->changes->local_extra_fields_read == 0) { e->changes->extra_fields = e->orig->extra_fields; e->changes->local_extra_fields_read = 1; } return 0; }