Skip to content

Commit d94bf22

Browse files
ddanilaclaude
andcommitted
libzip: backport security fixes for CVE-2012-1162, CVE-2012-1163, CVE-2015-2331
Backport fixes for multiple security vulnerabilities to bundled libzip 0.6.1. A full library upgrade is not feasible due to breaking API changes in libzip 0.11+. Fixes: - CVE-2012-1162: heap buffer overflow in _zip_readcdir when nentry is 0 but central directory data is present. Initialize directory entries before reading to prevent use of uninitialized memory. - CVE-2012-1163: integer overflow in central directory size calculation. Validate cd->size + cd->comment_len + EOCDLEN does not wrap. Add overflow guards before size*nentry allocations. - CVE-2015-2331: integer overflow in _zip_cdir_new when computing allocation size for large nentry values on 32-bit systems. - Fix memory leaks on error paths in _zip_dirent_read where partial allocations (filename, extrafield, comment) were not freed on subsequent allocation failures (related to CVE-2017-12858). - Replace deprecated stricmp with portable strcasecmp in zip_name_locate. Note: CVE-2011-0421 was already patched in the bundled copy. CVE-2017-14107 does not apply (no ZIP64 support in 0.6.1). CVE-2017-12858 and CVE-2019-17582 manifest differently in 0.6.1 (memory leak, not double-free/use-after-free) and are addressed by the error-path cleanup above. Reference: open-watcom#1369 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent bea1313 commit d94bf22

3 files changed

Lines changed: 44 additions & 7 deletions

File tree

contrib/libzip/lib/zdirent.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <stdlib.h>
4040
#include <string.h>
4141
#include <errno.h>
42+
#include <stddef.h>
4243
#include <sys/types.h>
4344

4445
#include "wio.h"
@@ -77,12 +78,20 @@ _zip_cdir_new(int nentry, struct zip_error *error)
7778
{
7879
struct zip_cdir *cd;
7980

81+
if (nentry < 0 || (nentry > 0 && (size_t)nentry > SIZE_MAX / sizeof(*(cd->entry)))) {
82+
_zip_error_set(error, ZIP_ER_MEMORY, 0);
83+
return NULL;
84+
}
85+
8086
if ((cd=ZIP_ALLOC(sizeof(*cd))) == NULL) {
8187
_zip_error_set(error, ZIP_ER_MEMORY, 0);
8288
return NULL;
8389
}
8490

85-
if ((cd->entry=ZIP_ALLOC(sizeof(*(cd->entry))*nentry)) == NULL) {
91+
if (nentry == 0) {
92+
cd->entry = NULL;
93+
}
94+
else if ((cd->entry=ZIP_ALLOC(sizeof(*(cd->entry))*nentry)) == NULL) {
8695
_zip_error_set(error, ZIP_ER_MEMORY, 0);
8796
ZIP_FREE(cd);
8897
return NULL;
@@ -282,14 +291,18 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
282291
if (zde->extrafield_len) {
283292
zde->extrafield = _zip_readstr(&cur, zde->extrafield_len, 0,
284293
error);
285-
if (!zde->extrafield)
294+
if (!zde->extrafield) {
295+
_zip_dirent_finalize(zde);
286296
return -1;
297+
}
287298
}
288299

289300
if (zde->comment_len) {
290301
zde->comment = _zip_readstr(&cur, zde->comment_len, 0, error);
291-
if (!zde->comment)
302+
if (!zde->comment) {
303+
_zip_dirent_finalize(zde);
292304
return -1;
305+
}
293306
}
294307
}
295308
else {
@@ -302,14 +315,18 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
302315
if (zde->extrafield_len) {
303316
zde->extrafield = _zip_readfpstr(fp, zde->extrafield_len, 0,
304317
error);
305-
if (!zde->extrafield)
318+
if (!zde->extrafield) {
319+
_zip_dirent_finalize(zde);
306320
return -1;
321+
}
307322
}
308323

309324
if (zde->comment_len) {
310325
zde->comment = _zip_readfpstr(fp, zde->comment_len, 0, error);
311-
if (!zde->comment)
326+
if (!zde->comment) {
327+
_zip_dirent_finalize(zde);
312328
return -1;
329+
}
313330
}
314331
}
315332

contrib/libzip/lib/znameloc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ _zip_name_locate(struct zip *za, const char *fname, int flags,
6565
return -1;
6666
}
6767

68-
cmp = (flags & ZIP_FL_NOCASE) ? stricmp : strcmp;
68+
cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
6969

7070
n = (flags & ZIP_FL_UNCHANGED) ? za->cdir->nentry : za->nentry;
7171
for (i=0; i<n; i++) {

contrib/libzip/lib/zopen.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <stdlib.h>
4040
#include <string.h>
4141
#include <errno.h>
42+
#include <stddef.h>
4243
#include <sys/types.h>
4344

4445
#include "wio.h"
@@ -193,7 +194,16 @@ zip_open(const char *fn, int flags, int *zep)
193194
return NULL;
194195
}
195196

196-
if ((za->entry=ZIP_ALLOC(sizeof(*(za->entry))*cdir->nentry)) == NULL) {
197+
if (cdir->nentry > 0
198+
&& (size_t)cdir->nentry > SIZE_MAX / sizeof(*(za->entry))) {
199+
set_error(zep, NULL, ZIP_ER_MEMORY);
200+
_zip_free(za);
201+
return NULL;
202+
}
203+
if (cdir->nentry == 0) {
204+
za->entry = NULL;
205+
}
206+
else if ((za->entry=ZIP_ALLOC(sizeof(*(za->entry))*cdir->nentry)) == NULL) {
197207
set_error(zep, NULL, ZIP_ER_MEMORY);
198208
_zip_free(za);
199209
return NULL;
@@ -269,6 +279,13 @@ _zip_readcdir(FILE *fp, unsigned char *buf, unsigned char *eocd, int buflen,
269279
cd->comment = NULL;
270280
cd->comment_len = _zip_read2(&cdp);
271281

282+
if (cd->size + cd->comment_len + EOCDLEN < cd->size) {
283+
/* integer overflow in size calculation */
284+
_zip_error_set(error, ZIP_ER_NOZIP, 0);
285+
_zip_cdir_free(cd);
286+
return NULL;
287+
}
288+
272289
/* some zip files are broken; their internal comment length
273290
says 0, but they have 1 or 2 comment bytes */
274291
if ((comlen-cd->comment_len < 0) || (comlen-cd->comment_len > 2)
@@ -309,6 +326,9 @@ _zip_readcdir(FILE *fp, unsigned char *buf, unsigned char *eocd, int buflen,
309326
}
310327
}
311328

329+
for (i=0; i<cd->nentry; i++)
330+
_zip_dirent_init(cd->entry+i);
331+
312332
for (i=0; i<cd->nentry; i++) {
313333
if ((_zip_dirent_read(cd->entry+i, fp, bufp, eocd-cdp, 0,
314334
error)) < 0) {

0 commit comments

Comments
 (0)