#1138160 unace: heap buffer over-read in magic scanner (CWE-125)

Package:
unace
Source:
unace
Description:
extract, test and view .ace archives
Submitter:
Xiang Chen
Date:
2026-05-29 03:51:02 UTC
Severity:
normal
Tags:
#1138160#5
Date:
2026-05-28 13:03:00 UTC
From:
To:
unace 1.2b has a heap buffer over-read in the ACE archive magic signature
scanner. The scanner reads input in 1024-byte chunks into a heap buffer
(malloc(0x400)) and performs 4-byte integer comparisons at every byte offset
0 through 1023. At offsets 1021 through 1023, the 4-byte read extends 1 to
3 bytes beyond the buffer boundary, reading adjacent heap memory.

The read data is compared against fixed magic constants and discarded on
mismatch, so information does not leak to the attacker directly. However,
the read itself is undefined behavior and may cause crashes on hardened
allocators or ASAN-instrumented builds.

Root cause (function at offset 0x3480 in the stripped binary):

buf = malloc(0x400); // 1024 bytes
n = read(fd, buf, 0x400); // fill buffer
for (i = 0; i < 0x400; i++) { // iterates 0..1023
if (*(uint32_t*)(buf + i) == MAGIC) ... // 4-byte read at buf+i
}

At i=1021, 1022, 1023: reads 4 bytes starting at buf+1021/1022/1023, which
extends 1/2/3 bytes past the 1024-byte allocation.

Trigger: processing any file where the ACE magic signature is not found
within the first 1018 bytes of a scan chunk (includes non-ACE files,
corrupt archives, and valid archives with padding).

Reproduction:

valgrind --tool=memcheck unace l /dev/null

# Or via Docker:
docker run --rm ubuntu:26.04 bash -c \
"apt-get update -qq && apt-get install -y -qq unace valgrind && \
dd if=/dev/urandom of=/tmp/test.ace bs=2048 count=1 2>/dev/null && \
valgrind unace l /tmp/test.ace 2>&1 | grep 'Invalid read'"

Expected valgrind output:
Invalid read of size 4
at 0x35CC: (in /usr/bin/unace)
Address 0x... is 0 bytes after a block of size 1,024 alloc'd

Suggested fix: change loop bound from i < 0x400 to i < (0x400 - 3), or
allocate 4 extra bytes: malloc(0x404).

Since this is a binary-only package with no upstream, options include binary
patching, adding a package advisory, or considering removal.

The software is proprietary, authored by e-merge GmbH (defunct ~2000), and
unmaintained. There is no upstream to notify. A CVE ID has been requested
via MITRE CNA-LR.

#1138160#10
Date:
2026-05-28 15:28:10 UTC
From:
To:
Hi!

Thanks for the report, will try to take a look and map that into the
actual source, but if you could do that, it would save me some time.

This package is neither proprietary nor binary-only, it contains source
and is free software, that's why it's in the main section of the Debian
archive. In addition there is readily available debug information as part
of the unace-dbgsym binary package, which could have helped with the
missing context here.

Thanks,
Guillem

#1138160#15
Date:
2026-05-29 02:34:07 UTC
From:
To:
Hi Guillem,

Thanks for the correction — I apologize for the error. I've now located
the source (unace_1.2b.orig.tar.gz) and mapped the issue. Here is the
source-level root cause and a proposed patch.

ROOT CAUSE (source level)
-------------------------

The bug is in read_arc_head() in unace.c. The function scans a
size_buf (1024) byte heap buffer for the 7-byte ACE magic signature
"**ACE**" (acesign_len = 7, defined in acestruc.h):

memset(buf, 0, size_buf);
...
fpos += read(archan, &buf[buf_pos], size_buf - buf_pos);

for (i = 0; i < size_buf; i++) // iterates 0..1023
{
if (!memcmp(acesign, &buf[i], acesign_len)) // 7-byte comparison
...
}

At offsets i = 1018 through 1023, the 7-byte memcmp reads 1 to 6 bytes
past the end of the 1024-byte buffer. (My original report incorrectly
described this as a 4-byte uint32_t comparison based on the binary
analysis — the source shows it is actually a 7-byte memcmp, making the
over-read larger than initially reported: up to 6 bytes, not 3.)

PROPOSED PATCH
--------------
--- a/unace.c +++ b/unace.c @@ -211,7 +211,7 @@ old_fpos = fpos; fpos += read(archan, &buf[buf_pos], size_buf - buf_pos); - for (i = 0; i < size_buf; i++) // look for the acesign + for (i = 0; i <= size_buf - acesign_len; i++) // look for the acesign { if (!memcmp(acesign, &buf[i], acesign_len)) { This stops the loop at offset 1018, so the last memcmp reads bytes 1018..1024 — exactly within bounds. Best regards, Xiang Chen
#1138160#20
Date:
2026-05-29 03:30:11 UTC
From:
To:
Hi!

Thanks again for the report, the analysis and the proposed fix. If you
get a CVE assigned, please let me know here, and I'll update the
references in the patch and the changelog. I'm uploading a fixed package
as I write this.

Thanks,
Guillem

#1138160#23
Date:
2026-05-29 03:32:45 UTC
From:
To:
Hi!

Bug #1138160 that you reported in package unace has been fixed
in the debian/pkgs/unace.git git repository. You can see the changelog below,
and you can check the diff of the fix at:

https://git.hadrons.org/cgit/debian/pkgs/unace.git/diff/?id=ef7600e
    Fix heap buffer over read when looking for the archive magic value

    We are searching for the file magic value within a 1024 buffer, and iterating
    over each byte in the buffer, comparing against the magic value, which is 7
    bytes long. But instead of stopping 6 bytes before the end of the buffer we
    continue until the last one, where we will have exceeded the memory for all
    of those 6 last comparisons.

    Closes: #1138160
    Reported-by: Xiang Chen <x14ngch3n@gmail.com>
    Patch-by: Xiang Chen <x14ngch3n@gmail.com>

diff --git a/debian/changelog b/debian/changelog
index 246e865..30f6eb6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -3,6 +3,8 @@ unace (1.2b-27) UNRELEASED; urgency=medium
   * Switch to Standards-Version 4.7.4 (no changes needed).
   * Switch Forwarded no to not-needed in patch metadata as there is no
     upstream anymore.
+  * Fix heap buffer over read when looking for the archive magic value.
+    Report and patch by Xiang Chen <x14ngch3n@gmail.com>. (Closes: #1138160)

#1138160#30
Date:
2026-05-29 03:48:36 UTC
From:
To:
We believe that the bug you reported is fixed in the latest version of
unace, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 1138160@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Guillem Jover <guillem@debian.org> (supplier of updated unace package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@ftp-master.debian.org)
Format: 1.8
Date: Fri, 29 May 2026 05:23:48 +0200
Source: unace
Architecture: source
Version: 1.2b-27
Distribution: unstable
Urgency: medium
Maintainer: Guillem Jover <guillem@debian.org>
Changed-By: Guillem Jover <guillem@debian.org>
Closes: 1138160
Changes:
 unace (1.2b-27) unstable; urgency=medium
 .
   * Switch to Standards-Version 4.7.4 (no changes needed).
   * Switch Forwarded no to not-needed in patch metadata as there is no
     upstream anymore.
   * Fix heap buffer over read when looking for the archive magic value.
     Report and patch by Xiang Chen <x14ngch3n@gmail.com>. (Closes: #1138160)
Checksums-Sha1:
 de90140f6997008573afdb0798bcd4ffbf601fb6 1907 unace_1.2b-27.dsc
 bbca77ba493e0d9a095097a59a22a83187a91ed5 10500 unace_1.2b-27.debian.tar.xz
 ceb04df6f4ea477c1fe1254e96501dc4da6b51e9 5819 unace_1.2b-27_amd64.buildinfo
Checksums-Sha256:
 678b1a1ecf91871ca2f42fe32e08b42e4e50c26ba7268c1d27dd74936ea642a5 1907 unace_1.2b-27.dsc
 c288924ddd431c224bf2b5d9720b706faa456956beefa579b74b3c2d8f10ce2b 10500 unace_1.2b-27.debian.tar.xz
 aa6269872b66eb4f0fb7c04d3be47b44810c059441399f562a5a2b041124aab2 5819 unace_1.2b-27_amd64.buildinfo
Files:
 699485f2a42a484f5c81e4a96ef9b21f 1907 utils optional unace_1.2b-27.dsc
 caabb828b3cbee8dbd836380303f4815 10500 utils optional unace_1.2b-27.debian.tar.xz
 405c57bad27572337d6259f8cf151b07 5819 utils optional unace_1.2b-27_amd64.buildinfo
-----BEGIN PGP SIGNATURE-----

wsG7BAEBCgBvBYJqGQiyCRC5cr8+pK5Xo0cUAAAAAAAeACBzYWx0QG5vdGF0aW9u
cy5zZXF1b2lhLXBncC5vcmdQPY047nNUsBErFaN6EOHTdiPB89qiJ0HCodZks95g
dhYhBE8+dPQ2BQwQ9WlldLlyvz6krlejAABDZw//cZcaAt+PheSYUYsgIY1mdcb9
7BGtZ7ktObE2E6XUuAGFZhqbk1HypE964VIDWsOvFXNuIrlU63xesqVlEDkFS7ab
uV6ehfxsSDv+5r0BCqnj2otVL0zLU0R+q5AMAj9rzUT2lair9I/40YmTVyTfLBg5
iBnata9k+BlX/ksHnnwnvr6hFh0TPkGgYjMw9k5Jb4eZkfCiUfakmOyh1SN4E0yu
6C7GnYdzA05AJSXxBwvQjDjKOfwynrIKDSkGLzG6yBwUgjxC59ahwX4Y8pNMyCGu
sEA5gVgfmsXVPSmlqZ0fgbtjGR51+bkqZd5sfKhUMEPhbYM/I4zCGTvAYxrjqYwX
oc3doNfCupkQs50PWEK3q/I8Qp1HfEHe6G3mi4Q/UPFzFQZeRusFwXKbz5I2uHIs
hu8XUO6vKtKZRPXxlY2RwdQ7246YPD33j1Oi1qrE3IUCpR3aW90XzBMQ2evRCLPG
Zwu2ygG4g0dj4u1Canu3kl8pj05YXPnON5JzhoOyDj4DjF4x7hSja+cqguNu5MBW
2BSaHk2xneS0IC8u4U+VDvXrBabuWM88wBrcsP3Czdh9zurOGZmwwkSwbgBxX22Y
dHPc50MCcrq1JX2bhG+b0ecE3dJjcHuH8LyJEcQpoRQTVhLybnJgvcnVZNnY9XT/
gOq9f3yueOanJl/IRh4=
=+q+w
-----END PGP SIGNATURE-----