Bug#1142906: unzip: heap buffer overflow WRITE in memextract() STORED path [CAN-2026-2034442]

Paul Marquess <[email protected]>
Newsgroups gmane.linux.debian.devel.bugs.rc
Message-ID <VI0P190MB2458D1E973A15C3F05C15CD8E5CC2@VI0P190MB2458.EURP190.PROD.OUTLOOK.COM>
Can you upload the zip file you used to generate the issue please?
________________________________
From: Akhil Koul <[email protected]>
Sent: 27 July 2026 19:09
To: [email protected] <[email protected]>
Subject: Bug#1142906: unzip: heap buffer overflow WRITE in memextract() STORED path [CAN-2026-2034442]

Package: unzip
Version: 6.0-28
Severity: grave
Tags: security
X-Debbugs-Cc: [email protected], [email protected]

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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.