@@ -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+
154158static 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) {
159163static 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