Skip to content

Commit d5996e4

Browse files
committed
Add more error codes from zip
1 parent b782ccd commit d5996e4

2 files changed

Lines changed: 43 additions & 25 deletions

File tree

src/include/otezip/zip.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ typedef struct otezip_error zip_error_t; /* error structure */
149149
#define ZIP_ER_EXISTS 10 /* File already exists */
150150
#define ZIP_ER_NOZIP 19 /* Not a zip archive */
151151
#define ZIP_ER_RDONLY 25 /* Read-only archive */
152+
#define ZIP_ER_OPEN 11 /* Can't open file */
153+
#define ZIP_ER_READ 5 /* Read error */
154+
#define ZIP_ER_INCONS 21 /* Zip archive inconsistent */
152155

153156
/* zip_stat flags */
154157
#define ZIP_STAT_NAME 0x0001u

src/lib/otezip.c

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ static void otezip_wr32(uint8_t *p, uint32_t v) {
151151

152152
/* ---- internal helpers ---- */
153153

154+
/* Return codes for error handling */
155+
#define OTEZIP_ERR_READ -1 /* File read/seek error */
156+
#define OTEZIP_ERR_INCONS -2 /* Archive structure inconsistent */
157+
154158
static inline int otezip_read_fully(FILE *fp, void *dst, size_t n) {
155159
return fread (dst, 1, n, fp) == n? 0: -1;
156160
}
@@ -159,11 +163,11 @@ static inline int otezip_read_fully(FILE *fp, void *dst, size_t n) {
159163
static long otezip_find_eocd(FILE *fp, uint8_t *eocd_out /*22+*/, size_t *cd_size, uint32_t *cd_ofs, uint16_t *total_entries) {
160164
long file_size;
161165
if (fseek (fp, 0, SEEK_END) != 0) {
162-
return -1;
166+
return OTEZIP_ERR_READ;
163167
}
164168
file_size = ftell (fp);
165169
if (file_size < 22) {
166-
return -1;
170+
return OTEZIP_ERR_INCONS;
167171
}
168172
const size_t max_back = 0x10000 + 22; /* spec: comment <= 65535 */
169173
/* Ensure both operands of the?: have the same unsigned type to avoid
@@ -172,11 +176,11 @@ static long otezip_find_eocd(FILE *fp, uint8_t *eocd_out /*22+*/, size_t *cd_siz
172176
size_t search_len = (file_size < (long)max_back)? (size_t)file_size: max_back;
173177

174178
if (fseek (fp, file_size - (long)search_len, SEEK_SET) != 0) {
175-
return -1;
179+
return OTEZIP_ERR_READ;
176180
}
177181
uint8_t buf[65558];
178182
if (otezip_read_fully (fp, buf, search_len) != 0) {
179-
return -1;
183+
return OTEZIP_ERR_READ;
180184
}
181185
size_t i;
182186
for (i = search_len - 22; i != (size_t)-1; --i) {
@@ -206,7 +210,7 @@ static long otezip_find_eocd(FILE *fp, uint8_t *eocd_out /*22+*/, size_t *cd_siz
206210
}
207211
}
208212
/* not found */
209-
return -1;
213+
return OTEZIP_ERR_INCONS;
210214
}
211215

212216
/* parse central directory into array of otezip_entry */
@@ -215,47 +219,50 @@ static int otezip_load_central(zip_t *za) {
215219
size_t cd_size;
216220
uint32_t cd_ofs;
217221
uint16_t n_entries;
222+
long eocd_pos;
218223

219-
if (otezip_find_eocd (za->fp, eocd, &cd_size, &cd_ofs, &n_entries) < 0) {
220-
return -1;
224+
eocd_pos = otezip_find_eocd (za->fp, eocd, &cd_size, &cd_ofs, &n_entries);
225+
if (eocd_pos < 0) {
226+
/* Return the specific error code from find_eocd */
227+
return (int)eocd_pos;
221228
}
222229

223230
/* Validate central directory against actual file size to avoid
224231
* out-of-bounds reads or huge allocations. */
225232
if (fseek (za->fp, 0, SEEK_END) != 0) {
226-
return -1;
233+
return OTEZIP_ERR_READ;
227234
}
228235
long file_size_long = ftell (za->fp);
229236
if (file_size_long < 0) {
230-
return -1;
237+
return OTEZIP_ERR_READ;
231238
}
232239
uint64_t file_size = (uint64_t)file_size_long;
233240
if ((uint64_t)cd_ofs + (uint64_t)cd_size > file_size) {
234-
return -1;
241+
return OTEZIP_ERR_INCONS;
235242
}
236243

237244
/* read entire central directory */
238245
if (fseek (za->fp, cd_ofs, SEEK_SET) != 0) {
239-
return -1;
246+
return OTEZIP_ERR_READ;
240247
}
241248
if (cd_size == 0) {
242-
return -1;
249+
return OTEZIP_ERR_INCONS;
243250
}
244251
uint8_t *cd_buf = (uint8_t *)malloc (cd_size);
245252
if (!cd_buf) {
246-
return -1;
253+
return OTEZIP_ERR_READ;
247254
}
248255
if (otezip_read_fully (za->fp, cd_buf, cd_size) != 0) {
249256
free (cd_buf);
250-
return -1;
257+
return OTEZIP_ERR_READ;
251258
}
252259

253260
za->entries = (struct otezip_entry *)calloc (n_entries, sizeof (struct otezip_entry));
254261
za->n_entries = n_entries;
255262

256263
if (!za->entries) {
257264
free (cd_buf);
258-
return -1;
265+
return OTEZIP_ERR_READ;
259266
}
260267

261268
size_t off = 0;
@@ -264,7 +271,7 @@ static int otezip_load_central(zip_t *za) {
264271
/* Ensure we have at least the fixed-size central header available */
265272
if (off + 46 > cd_size || otezip_rd32 (cd_buf + off) != MZIP_SIG_CDH) {
266273
free (cd_buf);
267-
return -1; /* malformed */
274+
return OTEZIP_ERR_INCONS; /* malformed */
268275
}
269276
const uint8_t *h = cd_buf + off;
270277

@@ -276,7 +283,7 @@ static int otezip_load_central(zip_t *za) {
276283
if (gp_flag & 0x0008) {
277284
fprintf (stderr, "mzip: data descriptors (general purpose flag bit 3) not supported\n");
278285
free (cd_buf);
279-
return -1;
286+
return OTEZIP_ERR_INCONS;
280287
}
281288

282289
uint16_t filename_len = otezip_rd16 (h + 28);
@@ -299,20 +306,20 @@ static int otezip_load_central(zip_t *za) {
299306
* more than our allowed maximum. */
300307
if ((uint64_t)e->comp_size > MZIP_MAX_PAYLOAD || (uint64_t)e->uncomp_size > MZIP_MAX_PAYLOAD) {
301308
free (cd_buf);
302-
return -1;
309+
return OTEZIP_ERR_INCONS;
303310
}
304311
e->external_attr = otezip_rd32 (h + 38);
305312

306313
e->name = (char *)malloc (filename_len + 1u);
307314
if (!e->name) {
308315
free (cd_buf);
309-
return -1;
316+
return OTEZIP_ERR_READ;
310317
}
311318
/* Ensure the filename bytes are within the central directory buffer */
312319
if ((size_t) (46 + filename_len) > cd_size - off) {
313320
free (e->name);
314321
free (cd_buf);
315-
return -1;
322+
return OTEZIP_ERR_INCONS;
316323
}
317324
memcpy (e->name, h + 46, filename_len);
318325
e->name[filename_len] = '\0';
@@ -321,7 +328,7 @@ static int otezip_load_central(zip_t *za) {
321328
uint64_t advance = 46 + (uint64_t)filename_len + (uint64_t)extra_len + (uint64_t)comment_len;
322329
if (advance > (uint64_t)cd_size - off) {
323330
free (cd_buf);
324-
return -1;
331+
return OTEZIP_ERR_INCONS;
325332
}
326333
off += (size_t)advance;
327334
}
@@ -678,19 +685,27 @@ zip_t *zip_open(const char *path, int flags, int *errorp) {
678685
FILE *fp = fopen (path, mode);
679686
if (!fp) {
680687
if (errorp) {
681-
*errorp = -1;
688+
*errorp = ZIP_ER_OPEN;
682689
}
683690
free (za);
684691
return NULL;
685692
}
686693
za->fp = fp;
687694
if (za->mode == 0 || (exists && ! (flags & ZIP_TRUNCATE))) {
688695
/* Load central directory for existing archive */
689-
if (otezip_load_central (za) != 0) {
690-
zip_close (za);
696+
int load_result = otezip_load_central (za);
697+
if (load_result != 0) {
698+
/* Convert internal error codes to libzip error codes */
691699
if (errorp) {
692-
*errorp = -1;
700+
if (load_result == OTEZIP_ERR_READ) {
701+
*errorp = ZIP_ER_READ;
702+
} else if (load_result == OTEZIP_ERR_INCONS) {
703+
*errorp = ZIP_ER_INCONS;
704+
} else {
705+
*errorp = ZIP_ER_NOZIP; /* Unknown error - not a zip */
706+
}
693707
}
708+
zip_close (za);
694709
return NULL;
695710
}
696711

0 commit comments

Comments
 (0)