Hi,
InfoZIP unzip 6.0 contains a heap buffer overflow WRITE in the
memextract() function (extract.c) when processing STORED-compressed
VMS extra field blocks. The allocation uses the declared uncompressed
size (usiz), but the STORED copy path uses the compressed data length
(G.incnt, derived from csiz). When csiz > usiz, memcpy writes past
the heap buffer.
CAN: CAN-2026-2034442 (pending assignment from MITRE)
CWE: CWE-122 (Heap-based Buffer Overflow)
CVSS: 8.5 High
ROOT CAUSE:
In extract_izvms_block() (extract.c, line 2645):
usiz = (cmptype == EB_IZVMS_BCSTOR ?
csiz : makeword(ebdata+EB_IZVMS_UCSIZ));
...
ucdata = (uch *)malloc(MAX(needlen, usiz)); // alloc'd with usiz
For the EB_IZVMS_BCDEFL case, memextract() is called:
memextract(__G__ ucdata, (ulg)usiz,
ebdata+EB_IZVMS_HLEN, (ulg)csiz);
Inside memextract() (extract.c, line 2523), the STORED path:
G.inptr = (uch *)src + (2 + 4);
G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4))); // from csiz
...
case STORED:
memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
The memcpy uses G.incnt (derived from srcsize/csiz) as the copy length,
but tgt is only usiz bytes. The method field inside the extra field data
is attacker-controlled — a crafted EF_IZVMS block declares
cmptype=EB_IZVMS_BCDEFL (to reach memextract) with a method byte of
STORED=0 inside the block data, usiz=16, and csiz=86. The memcpy then
copies 80 bytes into a 16-byte buffer.
TRIGGER: unzip -a -o poc.zip where poc.zip has version_made_by=0x0214
(VMS host system) and contains a crafted EF_IZVMS extra field with
the above geometry.
ASAN OUTPUT:
==8==ERROR: AddressSanitizer: heap-buffer-overflow on address
0xffff98400740 at pc 0xaaaacd723054
WRITE of size 80 at 0xffff98400740 thread T0
#0 __asan_memcpy
#1 memextract /build/unzip-6.0/extract.c:2523:13
#2 extract_izvms_block /build/unzip-6.0/extract.c:2660:13
#3 is_vms_varlen_txt /build/unzip-6.0/fileio.c:1181:32
#4 flush /build/unzip-6.0/fileio.c:896:17
#5 extract_or_test_member /build/unzip-6.0/extract.c:1921:21
0xffff98400740 is located 0 bytes to the right of 16-byte region
[0xffff98400730,0xffff98400740)
allocated by thread T0 here:
#1 extract_izvms_block /build/unzip-6.0/extract.c:2645:26
IMPACT: Heap buffer overflow WRITE with attacker-controlled length
(csiz - usiz - 6 bytes written past the allocation). This is a
write primitive — potential for code execution depending on heap
layout. Triggered during normal extraction of a crafted ZIP file.
SUGGESTED FIX (in memextract, STORED case):
case STORED:
+ if ((extent)G.incnt > tgtsize) {
+ error = PK_ERR;
+ break;
+ }
memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
Or equivalently, validate in extract_izvms_block() that csiz <= usiz + 6
before calling memextract with cmptype BCDEFL.
Best regards,
Akhil Koul