Rizin
unix-like reverse engineering framework and cli tools
zip_open.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zipint.h"

Go to the source code of this file.

Enumerations

enum  exists_t { EXISTS_ERROR = -1 , EXISTS_NOT = 0 , EXISTS_OK }
 

Functions

static zip_t_zip_allocate_new (zip_source_t *src, unsigned int flags, zip_error_t *error)
 
static zip_int64_t _zip_checkcons (zip_t *za, zip_cdir_t *cdir, zip_error_t *error)
 
static zip_cdir_t_zip_find_central_dir (zip_t *za, zip_uint64_t len)
 
static exists_t _zip_file_exists (zip_source_t *src, zip_error_t *error)
 
static int _zip_headercomp (const zip_dirent_t *, const zip_dirent_t *)
 
static unsigned char * _zip_memmem (const unsigned char *, size_t, const unsigned char *, size_t)
 
static zip_cdir_t_zip_read_cdir (zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error)
 
static zip_cdir_t_zip_read_eocd (zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error)
 
static zip_cdir_t_zip_read_eocd64 (zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error)
 
ZIP_EXTERN zip_tzip_open (const char *fn, int _flags, int *zep)
 
ZIP_EXTERN zip_tzip_open_from_source (zip_source_t *src, int _flags, zip_error_t *error)
 
zip_t_zip_open (zip_source_t *src, unsigned int flags, zip_error_t *error)
 
void _zip_set_open_error (int *zep, const zip_error_t *err, int ze)
 

Enumeration Type Documentation

◆ exists_t

enum exists_t
Enumerator
EXISTS_ERROR 
EXISTS_NOT 
EXISTS_OK 

Definition at line 41 of file zip_open.c.

exists_t
Definition: zip_open.c:41
@ EXISTS_NOT
Definition: zip_open.c:41
@ EXISTS_ERROR
Definition: zip_open.c:41
@ EXISTS_OK
Definition: zip_open.c:41

Function Documentation

◆ _zip_allocate_new()

static zip_t * _zip_allocate_new ( zip_source_t src,
unsigned int  flags,
zip_error_t error 
)
static

Definition at line 504 of file zip_open.c.

504  {
505  zip_t *za;
506 
507  if ((za = _zip_new(error)) == NULL) {
508  return NULL;
509  }
510 
511  za->src = src;
512  za->open_flags = flags;
513  if (flags & ZIP_RDONLY) {
514  za->flags |= ZIP_AFL_RDONLY;
516  }
517  return za;
518 }
lzma_index * src
Definition: index.h:567
#define NULL
Definition: cris-opc.c:27
#define ZIP_AFL_RDONLY
Definition: zip.h:94
#define ZIP_RDONLY
Definition: zip.h:71
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
Definition: zipint.h:278
unsigned int flags
Definition: zipint.h:283
unsigned int ch_flags
Definition: zipint.h:284
zip_source_t * src
Definition: zipint.h:279
unsigned int open_flags
Definition: zipint.h:280
void error(const char *msg)
Definition: untgz.c:593
zip_t * _zip_new(zip_error_t *error)
Definition: zip_new.c:45
zip_t * za
Definition: ziptool.c:79

References _zip_new(), zip::ch_flags, error(), flags, zip::flags, NULL, zip::open_flags, zip::src, src, za, ZIP_AFL_RDONLY, and ZIP_RDONLY.

Referenced by _zip_open(), and zip_open_from_source().

◆ _zip_checkcons()

static zip_int64_t _zip_checkcons ( zip_t za,
zip_cdir_t cdir,
zip_error_t error 
)
static

Definition at line 418 of file zip_open.c.

418  {
419  zip_uint64_t i;
420  zip_uint64_t min, max, j;
421  struct zip_dirent temp;
422 
423  _zip_dirent_init(&temp);
424  if (cd->nentry) {
425  max = cd->entry[0].orig->offset;
426  min = cd->entry[0].orig->offset;
427  }
428  else
429  min = max = 0;
430 
431  for (i = 0; i < cd->nentry; i++) {
432  if (cd->entry[i].orig->offset < min)
433  min = cd->entry[i].orig->offset;
434  if (min > (zip_uint64_t)cd->offset) {
436  return -1;
437  }
438 
439  j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE;
440  if (j > max)
441  max = j;
442  if (max > (zip_uint64_t)cd->offset) {
444  return -1;
445  }
446 
447  if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) {
449  return -1;
450  }
451 
452  if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) {
455  }
456  _zip_dirent_finalize(&temp);
457  return -1;
458  }
459 
460  if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) {
462  _zip_dirent_finalize(&temp);
463  return -1;
464  }
465 
466  cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields);
467  cd->entry[i].orig->local_extra_fields_read = 1;
468  temp.extra_fields = NULL;
469 
470  _zip_dirent_finalize(&temp);
471  }
472 
473  return (max - min) < ZIP_INT64_MAX ? (zip_int64_t)(max - min) : ZIP_INT64_MAX;
474 }
lzma_index ** i
Definition: index.h:629
static csh cd
Definition: asm_mips_cs.c:10
int max
Definition: enough.c:225
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int)
Definition: zip_error.c:126
ZIP_EXTERN int zip_error_code_system(const zip_error_t *_Nonnull)
Definition: zip_error.c:40
ZIP_EXTERN int zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int)
ZIP_EXTERN int zip_error_code_zip(const zip_error_t *_Nonnull)
Definition: zip_error.c:46
#define ZIP_ER_NOZIP
Definition: zip.h:124
#define ZIP_ER_INCONS
Definition: zip.h:126
#define min(a, b)
Definition: qsort.h:83
#define SEEK_SET
Definition: zip.c:88
void _zip_dirent_init(zip_dirent_t *de)
Definition: zip_dirent.c:268
void _zip_dirent_finalize(zip_dirent_t *zde)
Definition: zip_dirent.c:234
zip_int64_t _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error)
Definition: zip_dirent.c:327
void _zip_error_set_from_source(zip_error_t *err, zip_source_t *src)
Definition: zip_error.c:135
zip_extra_field_t * _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from)
static int _zip_headercomp(const zip_dirent_t *, const zip_dirent_t *)
Definition: zip_open.c:482
zip_uint16_t _zip_string_length(const zip_string_t *s)
Definition: zip_string.c:112
uint64_t zip_uint64_t
Definition: zipconf.h:39
#define ZIP_INT64_MAX
Definition: zipconf.h:54
int64_t zip_int64_t
Definition: zipconf.h:38
#define LENTRYSIZE
Definition: zipint.h:58
#define MAKE_DETAIL_WITH_INDEX(error, index)
Definition: zipint.h:207
#define ADD_INDEX_TO_DETAIL(error, index)
Definition: zipint.h:210
#define ZIP_ER_DETAIL_ENTRY_HEADER_MISMATCH
Definition: zipint.h:219

References _zip_dirent_finalize(), _zip_dirent_init(), _zip_dirent_read(), _zip_ef_merge(), _zip_error_set_from_source(), _zip_headercomp(), _zip_string_length(), ADD_INDEX_TO_DETAIL, cd, error(), zip_dirent::extra_fields, i, LENTRYSIZE, MAKE_DETAIL_WITH_INDEX, max, min, NULL, SEEK_SET, zip::src, za, ZIP_ER_DETAIL_ENTRY_HEADER_MISMATCH, ZIP_ER_INCONS, ZIP_ER_NOZIP, zip_error_code_system(), zip_error_code_zip(), zip_error_set(), ZIP_INT64_MAX, and zip_source_seek().

Referenced by _zip_find_central_dir().

◆ _zip_file_exists()

static exists_t _zip_file_exists ( zip_source_t src,
zip_error_t error 
)
static

Definition at line 525 of file zip_open.c.

525  {
526  struct zip_stat st;
527 
528  zip_stat_init(&st);
529  if (zip_source_stat(src, &st) != 0) {
530  zip_error_t *src_error = zip_source_error(src);
531  if (zip_error_code_zip(src_error) == ZIP_ER_READ && zip_error_code_system(src_error) == ENOENT) {
532  return EXISTS_NOT;
533  }
534  _zip_error_copy(error, src_error);
535  return EXISTS_ERROR;
536  }
537 
538  return EXISTS_OK;
539 }
ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull)
Definition: zip_stat_init.c:40
ZIP_EXTERN zip_error_t *_Nonnull zip_source_error(zip_source_t *_Nonnull)
ZIP_EXTERN int zip_source_stat(zip_source_t *_Nonnull, zip_stat_t *_Nonnull)
#define ZIP_ER_READ
Definition: zip.h:110
#define ENOENT
Definition: sftypes.h:112
Definition: zip.h:284
Definition: zip.h:300
void _zip_error_copy(zip_error_t *dst, const zip_error_t *src)
Definition: zip_error.c:102

References _zip_error_copy(), ENOENT, error(), EXISTS_ERROR, EXISTS_NOT, EXISTS_OK, src, ZIP_ER_READ, zip_error_code_system(), zip_error_code_zip(), zip_source_error(), zip_source_stat(), and zip_stat_init().

Referenced by zip_open_from_source().

◆ _zip_find_central_dir()

static zip_cdir_t * _zip_find_central_dir ( zip_t za,
zip_uint64_t  len 
)
static

Definition at line 543 of file zip_open.c.

543  {
544  zip_cdir_t *cdir, *cdirnew;
546  zip_int64_t buf_offset;
548  zip_int64_t a;
549  zip_int64_t best;
552 
553  if (len < EOCDLEN) {
555  return NULL;
556  }
557 
558  buflen = (len < CDBUFSIZE ? len : CDBUFSIZE);
560  zip_error_t *src_error = zip_source_error(za->src);
561  if (zip_error_code_zip(src_error) != ZIP_ER_SEEK || zip_error_code_system(src_error) != EFBIG) {
562  /* seek before start of file on my machine */
563  _zip_error_copy(&za->error, src_error);
564  return NULL;
565  }
566  }
567  if ((buf_offset = zip_source_tell(za->src)) < 0) {
569  return NULL;
570  }
571 
573  return NULL;
574  }
575 
576  best = -1;
577  cdir = NULL;
578  if (buflen >= CDBUFSIZE) {
579  /* EOCD64 locator is before EOCD, so leave place for it */
581  }
583 
585  while ((match = _zip_memmem(match, _zip_buffer_left(buffer) - (EOCDLEN - 4), (const unsigned char *)EOCD_MAGIC, 4)) != NULL) {
587  if ((cdirnew = _zip_read_cdir(za, buffer, (zip_uint64_t)buf_offset, &error)) != NULL) {
588  if (cdir) {
589  if (best <= 0) {
590  best = _zip_checkcons(za, cdir, &error);
591  }
592 
593  a = _zip_checkcons(za, cdirnew, &error);
594  if (best < a) {
595  _zip_cdir_free(cdir);
596  cdir = cdirnew;
597  best = a;
598  }
599  else {
600  _zip_cdir_free(cdirnew);
601  }
602  }
603  else {
604  cdir = cdirnew;
605  if (za->open_flags & ZIP_CHECKCONS)
606  best = _zip_checkcons(za, cdir, &error);
607  else {
608  best = 0;
609  }
610  }
611  cdirnew = NULL;
612  }
613 
614  match++;
616  }
617 
619 
620  if (best < 0) {
622  _zip_cdir_free(cdir);
623  return NULL;
624  }
625 
626  return cdir;
627 }
size_t len
Definition: 6502dis.c:15
struct buffer buffer
unsigned char match[65280+2]
Definition: gun.c:165
#define ZIP_ER_SEEK
Definition: zip.h:109
#define ZIP_CHECKCONS
Definition: zip.h:69
ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *_Nonnull)
#define EFBIG
Definition: sftypes.h:137
#define a(i)
Definition: sha256.c:41
Definition: buffer.h:15
Definition: engine.c:71
zip_error_t error
Definition: zipint.h:281
ut64 buflen
Definition: core.c:76
#define SEEK_END
Definition: zip.c:84
zip_uint8_t * _zip_buffer_data(zip_buffer_t *buffer)
Definition: zip_buffer.c:40
zip_uint64_t _zip_buffer_left(zip_buffer_t *buffer)
Definition: zip_buffer.c:128
void _zip_buffer_free(zip_buffer_t *buffer)
Definition: zip_buffer.c:46
zip_buffer_t * _zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error)
Definition: zip_buffer.c:174
int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset)
Definition: zip_buffer.c:297
zip_uint8_t * _zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length)
Definition: zip_buffer.c:66
void _zip_cdir_free(zip_cdir_t *cd)
Definition: zip_dirent.c:49
static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error)
Definition: zip_open.c:418
static zip_cdir_t * _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error)
Definition: zip_open.c:243
static unsigned char * _zip_memmem(const unsigned char *, size_t, const unsigned char *, size_t)
Definition: zip_open.c:631
uint8_t zip_uint8_t
Definition: zipconf.h:33
#define EOCD_MAGIC
Definition: zipint.h:53
#define EOCDLEN
Definition: zipint.h:61
#define CDBUFSIZE
Definition: zipint.h:64
#define EOCD64LOCLEN
Definition: zipint.h:62

References _zip_buffer_data(), _zip_buffer_free(), _zip_buffer_get(), _zip_buffer_left(), _zip_buffer_new_from_source(), _zip_buffer_set_offset(), _zip_cdir_free(), _zip_checkcons(), _zip_error_copy(), _zip_error_set_from_source(), _zip_memmem(), _zip_read_cdir(), a, buflen, CDBUFSIZE, EFBIG, EOCD64LOCLEN, EOCD_MAGIC, EOCDLEN, zip::error, error(), len, match, NULL, zip::open_flags, SEEK_END, zip::src, za, ZIP_CHECKCONS, ZIP_ER_NOZIP, ZIP_ER_SEEK, zip_error_code_system(), zip_error_code_zip(), zip_error_set(), zip_source_error(), zip_source_seek(), and zip_source_tell().

Referenced by _zip_open().

◆ _zip_headercomp()

static int _zip_headercomp ( const zip_dirent_t central,
const zip_dirent_t local 
)
static

Definition at line 482 of file zip_open.c.

482  {
483  if ((central->version_needed < local->version_needed)
484 #if 0
485  /* some zip-files have different values in local
486  and global headers for the bitflags */
487  || (central->bitflags != local->bitflags)
488 #endif
489  || (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_zip_string_equal(central->filename, local->filename))
490  return -1;
491 
492  if ((central->crc != local->crc) || (central->comp_size != local->comp_size) || (central->uncomp_size != local->uncomp_size)) {
493  /* InfoZip stores valid values in local header even when data descriptor is used.
494  This is in violation of the appnote. */
495  if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0))
496  return -1;
497  }
498 
499  return 0;
500 }
#define local
Definition: blast.c:36
zip_uint16_t bitflags
Definition: zipint.h:335
time_t last_mod
Definition: zipint.h:337
zip_uint64_t uncomp_size
Definition: zipint.h:340
zip_uint32_t crc
Definition: zipint.h:338
zip_int32_t comp_method
Definition: zipint.h:336
zip_uint64_t comp_size
Definition: zipint.h:339
zip_uint16_t version_needed
Definition: zipint.h:334
zip_string_t * filename
Definition: zipint.h:341
int _zip_string_equal(const zip_string_t *a, const zip_string_t *b)
Definition: zip_string.c:55
#define ZIP_GPBF_DATA_DESCRIPTOR
Definition: zipint.h:237

References _zip_string_equal(), zip_dirent::bitflags, zip_dirent::comp_method, zip_dirent::comp_size, zip_dirent::crc, zip_dirent::filename, zip_dirent::last_mod, local, zip_dirent::uncomp_size, zip_dirent::version_needed, and ZIP_GPBF_DATA_DESCRIPTOR.

Referenced by _zip_checkcons().

◆ _zip_memmem()

static unsigned char * _zip_memmem ( const unsigned char *  big,
size_t  biglen,
const unsigned char *  little,
size_t  littlelen 
)
static

Definition at line 631 of file zip_open.c.

631  {
632  const unsigned char *p;
633 
634  if ((biglen < littlelen) || (littlelen == 0))
635  return NULL;
636  p = big - 1;
637  while ((p = (const unsigned char *)memchr(p + 1, little[0], (size_t)(big - (p + 1)) + (size_t)(biglen - littlelen) + 1)) != NULL) {
638  if (memcmp(p + 1, little + 1, littlelen - 1) == 0)
639  return (unsigned char *)p;
640  }
641 
642  return NULL;
643 }
void * p
Definition: libc.cpp:67

References NULL, and p.

Referenced by _zip_find_central_dir().

◆ _zip_open()

zip_t* _zip_open ( zip_source_t src,
unsigned int  flags,
zip_error_t error 
)

Definition at line 146 of file zip_open.c.

146  {
147  zip_t *za;
148  zip_cdir_t *cdir;
149  struct zip_stat st;
151 
152  zip_stat_init(&st);
153  if (zip_source_stat(src, &st) < 0) {
155  return NULL;
156  }
157  if ((st.valid & ZIP_STAT_SIZE) == 0) {
159  return NULL;
160  }
161  len = st.size;
162 
163 
164  if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
165  return NULL;
166  }
167 
168  /* treat empty files as empty archives */
169  if (len == 0 && zip_source_accept_empty(src)) {
170  return za;
171  }
172 
173  if ((cdir = _zip_find_central_dir(za, len)) == NULL) {
175  /* keep src so discard does not get rid of it */
177  zip_discard(za);
178  return NULL;
179  }
180 
181  za->entry = cdir->entry;
182  za->nentry = cdir->nentry;
183  za->nentry_alloc = cdir->nentry_alloc;
184  za->comment_orig = cdir->comment;
185 
186  free(cdir);
187 
189 
190  for (idx = 0; idx < za->nentry; idx++) {
192  if (name == NULL) {
193  /* keep src so discard does not get rid of it */
195  zip_discard(za);
196  return NULL;
197  }
198 
199  if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) {
200  if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) {
202  /* keep src so discard does not get rid of it */
204  zip_discard(za);
205  return NULL;
206  }
207  }
208  }
209 
210  za->ch_flags = za->flags;
211 
212  return za;
213 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
#define ZIP_ER_EXISTS
Definition: zip.h:115
#define ZIP_STAT_SIZE
Definition: zip.h:292
ZIP_EXTERN void zip_discard(zip_t *_Nonnull)
Definition: zip_discard.c:45
#define ZIP_FL_UNCHANGED
Definition: zip.h:79
ZIP_EXTERN void zip_source_keep(zip_source_t *_Nonnull)
int idx
Definition: setup.py:197
#define EOPNOTSUPP
Definition: sftypes.h:155
Definition: z80asm.h:102
zip_string_t * comment
Definition: zipint.h:363
zip_entry_t * entry
Definition: zipint.h:357
zip_uint64_t nentry
Definition: zipint.h:358
zip_uint64_t nentry_alloc
Definition: zipint.h:359
zip_dirent_t * orig
Definition: zipint.h:409
int zip_err
Definition: zip.h:285
zip_entry_t * entry
Definition: zipint.h:294
zip_uint64_t nentry_alloc
Definition: zipint.h:293
zip_uint64_t nentry
Definition: zipint.h:292
zip_string_t * comment_orig
Definition: zipint.h:288
zip_hash_t * names
Definition: zipint.h:300
bool _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error)
Definition: zip_hash.c:347
bool _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error)
Definition: zip_hash.c:205
static zip_t * _zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error)
Definition: zip_open.c:504
static zip_cdir_t * _zip_find_central_dir(zip_t *za, zip_uint64_t len)
Definition: zip_open.c:543
bool zip_source_accept_empty(zip_source_t *src)
const zip_uint8_t * _zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip_error_t *error)
Definition: zip_string.c:80

References _zip_allocate_new(), _zip_error_copy(), _zip_error_set_from_source(), _zip_find_central_dir(), _zip_hash_add(), _zip_hash_reserve_capacity(), _zip_string_get(), zip::ch_flags, zip_cdir::comment, zip::comment_orig, zip::entry, zip_cdir::entry, EOPNOTSUPP, zip::error, error(), zip_dirent::filename, flags, zip::flags, free(), setup::idx, len, zip::names, zip::nentry, zip_cdir::nentry, zip::nentry_alloc, zip_cdir::nentry_alloc, NULL, zip_entry::orig, zip_stat::size, src, zip_stat::valid, za, ZIP_CHECKCONS, zip_discard(), ZIP_ER_EXISTS, ZIP_ER_SEEK, zip_error::zip_err, zip_error_set(), ZIP_FL_UNCHANGED, zip_source_accept_empty(), zip_source_keep(), zip_source_stat(), zip_stat_init(), and ZIP_STAT_SIZE.

Referenced by zip_open_from_source().

◆ _zip_read_cdir()

static zip_cdir_t * _zip_read_cdir ( zip_t za,
zip_buffer_t buffer,
zip_uint64_t  buf_offset,
zip_error_t error 
)
static

Definition at line 243 of file zip_open.c.

243  {
244  zip_cdir_t *cd;
245  zip_uint16_t comment_len;
246  zip_uint64_t i, left;
247  zip_uint64_t eocd_offset = _zip_buffer_offset(buffer);
248  zip_buffer_t *cd_buffer;
249 
251  /* not enough bytes left for comment */
253  return NULL;
254  }
255 
256  /* check for end-of-central-dir magic */
257  if (memcmp(_zip_buffer_get(buffer, 4), EOCD_MAGIC, 4) != 0) {
259  return NULL;
260  }
261 
262  if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) {
264  cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error);
265  }
266  else {
267  _zip_buffer_set_offset(buffer, eocd_offset);
268  cd = _zip_read_eocd(buffer, buf_offset, za->flags, error);
269  }
270 
271  if (cd == NULL)
272  return NULL;
273 
274  _zip_buffer_set_offset(buffer, eocd_offset + 20);
275  comment_len = _zip_buffer_get_16(buffer);
276 
277  if (cd->offset + cd->size > buf_offset + eocd_offset) {
278  /* cdir spans past EOCD record */
281  return NULL;
282  }
283 
284  if (comment_len || (za->open_flags & ZIP_CHECKCONS)) {
285  zip_uint64_t tail_len;
286 
287  _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN);
288  tail_len = _zip_buffer_left(buffer);
289 
290  if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) {
293  return NULL;
294  }
295 
296  if (comment_len) {
297  if ((cd->comment = _zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) {
299  return NULL;
300  }
301  }
302  }
303 
304  if (cd->offset >= buf_offset) {
305  zip_uint8_t *data;
306  /* if buffer already read in, use it */
307  _zip_buffer_set_offset(buffer, cd->offset - buf_offset);
308 
309  if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) {
312  return NULL;
313  }
314  if ((cd_buffer = _zip_buffer_new(data, cd->size)) == NULL) {
317  return NULL;
318  }
319  }
320  else {
321  cd_buffer = NULL;
322 
323  if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) {
326  return NULL;
327  }
328 
329  /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */
330  if (zip_source_tell(za->src) != (zip_int64_t)cd->offset) {
333  return NULL;
334  }
335  }
336 
337  left = (zip_uint64_t)cd->size;
338  i = 0;
339  while (left > 0) {
340  bool grown = false;
341  zip_int64_t entry_size;
342 
343  if (i == cd->nentry) {
344  /* InfoZIP has a hack to avoid using Zip64: it stores nentries % 0x10000 */
345  /* This hack isn't applicable if we're using Zip64, or if there is no central directory entry following. */
346 
347  if (cd->is_zip64 || left < CDENTRYSIZE) {
348  break;
349  }
350 
351  if (!_zip_cdir_grow(cd, 0x10000, error)) {
353  _zip_buffer_free(cd_buffer);
354  return NULL;
355  }
356  grown = true;
357  }
358 
359  if ((cd->entry[i].orig = _zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) {
362  }
363  else if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) {
365  }
367  _zip_buffer_free(cd_buffer);
368  return NULL;
369  }
370  i++;
371  left -= (zip_uint64_t)entry_size;
372  }
373 
374  if (i != cd->nentry || left > 0) {
376  _zip_buffer_free(cd_buffer);
378  return NULL;
379  }
380 
381  if (za->open_flags & ZIP_CHECKCONS) {
382  bool ok;
383 
384  if (cd_buffer) {
385  ok = _zip_buffer_eof(cd_buffer);
386  }
387  else {
389 
390  if (offset < 0) {
393  return NULL;
394  }
395  ok = ((zip_uint64_t)offset == cd->offset + cd->size);
396  }
397 
398  if (!ok) {
400  _zip_buffer_free(cd_buffer);
402  return NULL;
403  }
404  }
405 
406  _zip_buffer_free(cd_buffer);
407  return cd;
408 }
voidpf uLong offset
Definition: ioapi.h:144
#define ZIP_ER_MEMORY
Definition: zip.h:119
#define ZIP_FL_ENC_GUESS
Definition: zip.h:82
@ ok
Definition: lz4.c:1706
while(len< limit &&buf1[len]==buf2[len])++len
zip_buffer_t * _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size)
Definition: zip_buffer.c:146
zip_uint16_t _zip_buffer_get_16(zip_buffer_t *buffer)
Definition: zip_buffer.c:80
bool _zip_buffer_eof(zip_buffer_t *buffer)
Definition: zip_buffer.c:60
zip_uint64_t _zip_buffer_offset(zip_buffer_t *buffer)
Definition: zip_buffer.c:192
zip_dirent_t * _zip_dirent_new(void)
Definition: zip_dirent.c:305
bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error)
Definition: zip_dirent.c:88
static zip_cdir_t * _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error)
Definition: zip_open.c:706
static zip_cdir_t * _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error)
Definition: zip_open.c:647
zip_string_t * _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, zip_error_t *error)
Definition: zip_string.c:121
uint16_t zip_uint16_t
Definition: zipconf.h:35
#define ZIP_ER_DETAIL_CDIR_WRONG_ENTRIES_COUNT
Definition: zipint.h:218
#define CDENTRYSIZE
Definition: zipint.h:57
#define ZIP_ER_DETAIL_CDIR_LENGTH_INVALID
Definition: zipint.h:216
#define ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD
Definition: zipint.h:214
#define EOCD64LOC_MAGIC
Definition: zipint.h:55
#define ZIP_ER_DETAIL_CDIR_ENTRY_INVALID
Definition: zipint.h:217
#define ZIP_ER_DETAIL_COMMENT_LENGTH_INVALID
Definition: zipint.h:215

References _zip_buffer_data(), _zip_buffer_eof(), _zip_buffer_free(), _zip_buffer_get(), _zip_buffer_get_16(), _zip_buffer_left(), _zip_buffer_new(), _zip_buffer_offset(), _zip_buffer_set_offset(), _zip_cdir_free(), _zip_cdir_grow(), _zip_dirent_new(), _zip_dirent_read(), _zip_error_set_from_source(), _zip_read_eocd(), _zip_read_eocd64(), _zip_string_new(), ADD_INDEX_TO_DETAIL, cd, CDENTRYSIZE, EOCD64LOC_MAGIC, EOCD64LOCLEN, EOCD_MAGIC, EOCDLEN, error(), zip::flags, i, MAKE_DETAIL_WITH_INDEX, NULL, ok, zip::open_flags, SEEK_SET, zip::src, while(), za, ZIP_CHECKCONS, ZIP_ER_DETAIL_CDIR_ENTRY_INVALID, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD, ZIP_ER_DETAIL_CDIR_WRONG_ENTRIES_COUNT, ZIP_ER_DETAIL_COMMENT_LENGTH_INVALID, ZIP_ER_INCONS, ZIP_ER_MEMORY, ZIP_ER_NOZIP, zip_error_code_system(), zip_error_code_zip(), zip_error_set(), ZIP_FL_ENC_GUESS, zip_source_seek(), and zip_source_tell().

Referenced by _zip_find_central_dir().

◆ _zip_read_eocd()

static zip_cdir_t * _zip_read_eocd ( zip_buffer_t buffer,
zip_uint64_t  buf_offset,
unsigned int  flags,
zip_error_t error 
)
static

Definition at line 647 of file zip_open.c.

647  {
648  zip_cdir_t *cd;
649  zip_uint64_t i, nentry, size, offset, eocd_offset;
650 
653  return NULL;
654  }
655 
656  eocd_offset = _zip_buffer_offset(buffer);
657 
658  _zip_buffer_get(buffer, 4); /* magic already verified */
659 
660  if (_zip_buffer_get_32(buffer) != 0) {
662  return NULL;
663  }
664 
665  /* number of cdir-entries on this disk */
667  /* number of cdir-entries */
668  nentry = _zip_buffer_get_16(buffer);
669 
670  if (nentry != i) {
672  return NULL;
673  }
674 
677 
678  if (offset + size < offset) {
680  return NULL;
681  }
682 
683  if (offset + size > buf_offset + eocd_offset) {
684  /* cdir spans past EOCD record */
686  return NULL;
687  }
688 
689  if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) {
691  return NULL;
692  }
693 
694  if ((cd = _zip_cdir_new(nentry, error)) == NULL)
695  return NULL;
696 
697  cd->is_zip64 = false;
698  cd->size = size;
699  cd->offset = offset;
700 
701  return cd;
702 }
voidpf void uLong size
Definition: ioapi.h:138
#define ZIP_ER_MULTIDISK
Definition: zip.h:106
zip_uint32_t _zip_buffer_get_32(zip_buffer_t *buffer)
Definition: zip_buffer.c:92
zip_cdir_t * _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error)
Definition: zip_dirent.c:64
#define ZIP_ER_DETAIL_EOCD_LENGTH_INVALID
Definition: zipint.h:220

References _zip_buffer_get(), _zip_buffer_get_16(), _zip_buffer_get_32(), _zip_buffer_left(), _zip_buffer_offset(), _zip_cdir_new(), cd, EFBIG, EOCDLEN, error(), flags, i, NULL, ZIP_CHECKCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD, ZIP_ER_DETAIL_EOCD_LENGTH_INVALID, ZIP_ER_INCONS, ZIP_ER_MULTIDISK, ZIP_ER_NOZIP, ZIP_ER_SEEK, and zip_error_set().

Referenced by _zip_read_cdir().

◆ _zip_read_eocd64()

static zip_cdir_t * _zip_read_eocd64 ( zip_source_t src,
zip_buffer_t buffer,
zip_uint64_t  buf_offset,
unsigned int  flags,
zip_error_t error 
)
static

Definition at line 706 of file zip_open.c.

706  {
707  zip_cdir_t *cd;
709  zip_uint8_t eocd[EOCD64LEN];
710  zip_uint64_t eocd_offset;
711  zip_uint64_t size, nentry, i, eocdloc_offset;
712  bool free_buffer;
713  zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64;
714 
715  eocdloc_offset = _zip_buffer_offset(buffer);
716 
717  _zip_buffer_get(buffer, 4); /* magic already verified */
718 
719  num_disks = _zip_buffer_get_16(buffer);
720  eocd_disk = _zip_buffer_get_16(buffer);
721  eocd_offset = _zip_buffer_get_64(buffer);
722 
723  /* valid seek value for start of EOCD */
724  if (eocd_offset > ZIP_INT64_MAX) {
726  return NULL;
727  }
728 
729  /* does EOCD fit before EOCD locator? */
730  if (eocd_offset + EOCD64LEN > eocdloc_offset + buf_offset) {
732  return NULL;
733  }
734 
735  /* make sure current position of buffer is beginning of EOCD */
736  if (eocd_offset >= buf_offset && eocd_offset + EOCD64LEN <= buf_offset + _zip_buffer_size(buffer)) {
737  _zip_buffer_set_offset(buffer, eocd_offset - buf_offset);
738  free_buffer = false;
739  }
740  else {
741  if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) {
743  return NULL;
744  }
746  return NULL;
747  }
748  free_buffer = true;
749  }
750 
751  if (memcmp(_zip_buffer_get(buffer, 4), EOCD64_MAGIC, 4) != 0) {
753  if (free_buffer) {
755  }
756  return NULL;
757  }
758 
759  /* size of EOCD */
761 
762  /* is there a hole between EOCD and EOCD locator, or do they overlap? */
763  if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) {
765  if (free_buffer) {
767  }
768  return NULL;
769  }
770 
771  _zip_buffer_get(buffer, 4); /* skip version made by/needed */
772 
773  num_disks64 = _zip_buffer_get_32(buffer);
774  eocd_disk64 = _zip_buffer_get_32(buffer);
775 
776  /* if eocd values are 0xffff, we have to use eocd64 values.
777  otherwise, if the values are not the same, it's inconsistent;
778  in any case, if the value is not 0, we don't support it */
779  if (num_disks == 0xffff) {
780  num_disks = num_disks64;
781  }
782  if (eocd_disk == 0xffff) {
783  eocd_disk = eocd_disk64;
784  }
785  if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) {
787  if (free_buffer) {
789  }
790  return NULL;
791  }
792  if (num_disks != 0 || eocd_disk != 0) {
794  if (free_buffer) {
796  }
797  return NULL;
798  }
799 
800  nentry = _zip_buffer_get_64(buffer);
802 
803  if (nentry != i) {
805  if (free_buffer) {
807  }
808  return NULL;
809  }
810 
813 
814  /* did we read past the end of the buffer? */
815  if (!_zip_buffer_ok(buffer)) {
817  if (free_buffer) {
819  }
820  return NULL;
821  }
822 
823  if (free_buffer) {
825  }
826 
827  if (offset > ZIP_INT64_MAX || offset + size < offset) {
829  return NULL;
830  }
831  if (offset + size > buf_offset + eocd_offset) {
832  /* cdir spans past EOCD record */
834  return NULL;
835  }
836  if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) {
838  return NULL;
839  }
840 
841  if (nentry > size / CDENTRYSIZE) {
843  return NULL;
844  }
845 
846  if ((cd = _zip_cdir_new(nentry, error)) == NULL)
847  return NULL;
848 
849  cd->is_zip64 = true;
850  cd->size = size;
851  cd->offset = offset;
852 
853  return cd;
854 }
#define ZIP_ER_INTERNAL
Definition: zip.h:125
zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer)
Definition: zip_buffer.c:322
bool _zip_buffer_ok(zip_buffer_t *buffer)
Definition: zip_buffer.c:198
zip_uint64_t _zip_buffer_get_64(zip_buffer_t *buffer)
Definition: zip_buffer.c:104
uint32_t zip_uint32_t
Definition: zipconf.h:37
#define ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD
Definition: zipint.h:221
#define ZIP_ER_DETAIL_EOCD64_WRONG_MAGIC
Definition: zipint.h:222
#define EOCD64LEN
Definition: zipint.h:63
#define ZIP_ER_DETAIL_EOCD64_MISMATCH
Definition: zipint.h:223
#define ZIP_ER_DETAIL_CDIR_INVALID
Definition: zipint.h:224
#define EOCD64_MAGIC
Definition: zipint.h:56

References _zip_buffer_free(), _zip_buffer_get(), _zip_buffer_get_16(), _zip_buffer_get_32(), _zip_buffer_get_64(), _zip_buffer_new_from_source(), _zip_buffer_offset(), _zip_buffer_ok(), _zip_buffer_set_offset(), _zip_buffer_size(), _zip_cdir_new(), _zip_error_set_from_source(), cd, CDENTRYSIZE, EFBIG, EOCD64_MAGIC, EOCD64LEN, error(), flags, i, NULL, SEEK_SET, src, ZIP_CHECKCONS, ZIP_ER_DETAIL_CDIR_INVALID, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD, ZIP_ER_DETAIL_EOCD64_MISMATCH, ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD, ZIP_ER_DETAIL_EOCD64_WRONG_MAGIC, ZIP_ER_INCONS, ZIP_ER_INTERNAL, ZIP_ER_MULTIDISK, ZIP_ER_SEEK, zip_error_set(), ZIP_INT64_MAX, and zip_source_seek().

Referenced by _zip_read_cdir().

◆ _zip_set_open_error()

void _zip_set_open_error ( int zep,
const zip_error_t err,
int  ze 
)

Definition at line 217 of file zip_open.c.

217  {
218  if (err) {
219  ze = zip_error_code_zip(err);
220  switch (zip_error_system_type(err)) {
221  case ZIP_ET_SYS:
222  case ZIP_ET_LIBZIP:
223  errno = zip_error_code_system(err);
224  break;
225 
226  default:
227  break;
228  }
229  }
230 
231  if (zep)
232  *zep = ze;
233 }
static bool err
Definition: armass.c:435
#define ZIP_ET_LIBZIP
Definition: zip.h:144
#define ZIP_ET_SYS
Definition: zip.h:142
ZIP_EXTERN int zip_error_system_type(const zip_error_t *_Nonnull)
Definition: zip_error.c:83

References err, zip_error_code_system(), zip_error_code_zip(), zip_error_system_type(), ZIP_ET_LIBZIP, and ZIP_ET_SYS.

Referenced by zip_fdopen(), and zip_open().

◆ zip_open()

ZIP_EXTERN zip_t* zip_open ( const char *  fn,
int  _flags,
int zep 
)

Definition at line 54 of file zip_open.c.

54  {
55  zip_t *za;
57  struct zip_error error;
58 
60  if ((src = zip_source_file_create(fn, 0, -1, &error)) == NULL) {
61  _zip_set_open_error(zep, &error, 0);
63  return NULL;
64  }
65 
66  if ((za = zip_open_from_source(src, _flags, &error)) == NULL) {
68  _zip_set_open_error(zep, &error, 0);
70  return NULL;
71  }
72 
74  return za;
75 }
ZIP_EXTERN void zip_error_init(zip_error_t *_Nonnull)
Definition: zip_error.c:59
ZIP_EXTERN void zip_error_fini(zip_error_t *_Nonnull)
Definition: zip_error.c:52
ZIP_EXTERN void zip_source_free(zip_source_t *_Nullable)
ZIP_EXTERN zip_source_t *_Nullable zip_source_file_create(const char *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable)
static const char struct stat static buf struct stat static buf static idle const char static path static fd const char static len const void static prot const char struct module static image struct kernel_sym static table unsigned char static buf static fsuid unsigned struct dirent unsigned static count const struct iovec static count static pid const void static len static flags const struct sched_param static p static pid static policy struct timespec static tp static suid unsigned fn
Definition: sflib.h:186
ZIP_EXTERN zip_t * zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error)
Definition: zip_open.c:79
void _zip_set_open_error(int *zep, const zip_error_t *err, int ze)
Definition: zip_open.c:217

References _zip_set_open_error(), error(), fn, NULL, src, za, zip_error_fini(), zip_error_init(), zip_open_from_source(), zip_source_file_create(), and zip_source_free().

Referenced by add_from_zip(), list_zip(), main(), merge_zip(), read_from_file(), and rz_io_zip_open_archive().

◆ zip_open_from_source()

ZIP_EXTERN zip_t* zip_open_from_source ( zip_source_t src,
int  _flags,
zip_error_t error 
)

Definition at line 79 of file zip_open.c.

79  {
80  unsigned int flags;
81  zip_int64_t supported;
82  exists_t exists;
83 
84  if (_flags < 0 || src == NULL) {
86  return NULL;
87  }
88  flags = (unsigned int)_flags;
89 
90  supported = zip_source_supports(src);
93  return NULL;
94  }
96  flags |= ZIP_RDONLY;
97  }
98 
101  return NULL;
102  }
103 
104  exists = _zip_file_exists(src, error);
105  switch (exists) {
106  case EXISTS_ERROR:
107  return NULL;
108 
109  case EXISTS_NOT:
110  if ((flags & ZIP_CREATE) == 0) {
112  return NULL;
113  }
114  return _zip_allocate_new(src, flags, error);
115 
116  default: {
117  zip_t *za;
118  if (flags & ZIP_EXCL) {
120  return NULL;
121  }
122  if (zip_source_open(src) < 0) {
124  return NULL;
125  }
126 
127  if (flags & ZIP_TRUNCATE) {
129  }
130  else {
131  /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */
132  za = _zip_open(src, flags, error);
133  }
134 
135  if (za == NULL) {
137  return NULL;
138  }
139  return za;
140  }
141  }
142 }
ZIP_EXTERN int zip_source_close(zip_source_t *_Nonnull)
#define ZIP_SOURCE_SUPPORTS_SEEKABLE
Definition: zip.h:256
#define ZIP_SOURCE_SUPPORTS_WRITABLE
Definition: zip.h:261
#define ZIP_EXCL
Definition: zip.h:68
#define ZIP_ER_NOENT
Definition: zip.h:114
#define ZIP_CREATE
Definition: zip.h:67
ZIP_EXTERN int zip_source_open(zip_source_t *_Nonnull)
#define ZIP_ER_RDONLY
Definition: zip.h:130
#define ZIP_ER_INVAL
Definition: zip.h:123
#define ZIP_TRUNCATE
Definition: zip.h:70
#define ZIP_ER_OPNOTSUPP
Definition: zip.h:133
static int
Definition: sfsocketcall.h:114
zip_t * _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
Definition: zip_open.c:146
static exists_t _zip_file_exists(zip_source_t *src, zip_error_t *error)
Definition: zip_open.c:525
zip_int64_t zip_source_supports(zip_source_t *src)

References _zip_allocate_new(), _zip_error_set_from_source(), _zip_file_exists(), _zip_open(), error(), EXISTS_ERROR, EXISTS_NOT, flags, int, NULL, src, za, ZIP_CREATE, ZIP_ER_EXISTS, ZIP_ER_INVAL, ZIP_ER_NOENT, ZIP_ER_OPNOTSUPP, ZIP_ER_RDONLY, zip_error_set(), ZIP_EXCL, ZIP_RDONLY, zip_source_close(), zip_source_open(), zip_source_supports(), ZIP_SOURCE_SUPPORTS_SEEKABLE, ZIP_SOURCE_SUPPORTS_WRITABLE, and ZIP_TRUNCATE.

Referenced by LLVMFuzzerTestOneInput(), main(), read_from_file(), read_hole(), read_to_memory(), windows_open(), zip_fdopen(), and zip_open().