Skip to content

ArHandler: backport 7-Zip 26.01 symbol table OOB read fix - #264

Open
tonghuaroot wants to merge 1 commit into
p7zip-project:masterfrom
tonghuaroot:fix/ar-symtab-oob-26.01
Open

ArHandler: backport 7-Zip 26.01 symbol table OOB read fix#264
tonghuaroot wants to merge 1 commit into
p7zip-project:masterfrom
tonghuaroot:fix/ar-symtab-oob-26.01

Conversation

@tonghuaroot

Copy link
Copy Markdown

Backports two hardenings landed in upstream 7-Zip 26.01 (released 2026-04-27).

What changed upstream

1. BSD ar symbol table: 4-byte OOB read

p7zip reads namesSize from p + namesStart and only validates the buffer afterwards:

```cpp
size_t namesStart = pos + tableSize;
UInt32 namesSize = Get32(p + namesStart, be); // <-- unchecked read
namesStart += 4;
if (namesStart > size || namesStart + namesSize != size)
continue;
```

26.01 adds an explicit pre-check so the 4-byte read is only performed when 4 bytes are available:

```cpp
size_t namesStart = pos + tableSize;
if (size - namesStart < 4)
continue;
UInt32 namesSize = Get32(p + namesStart, be);
namesStart += 4;
if (namesStart + namesSize != size)
continue;
```

2. GNU ar / Microsoft .lib: 32-bit index arithmetic

The symbol-table iteration uses bare i * 4, i * 2, and index * 4 arithmetic which is performed in 32-bit and then implicitly widened on dereference. 26.01 casts the multiplicand to (size_t) so the math is done at pointer width on 64-bit platforms, removing the risk of wrap when numSymbols / numMembers approach 2^30.

Patch

Three small hunks, byte-for-byte matching upstream 26.01.

Disclosure

I am not a native English speaker. AI tooling was used to polish the prose in this PR description. The fix itself is a direct backport from upstream 7-Zip 26.01 source; no design choices were made beyond matching upstream verbatim.

Upstream 7-Zip 26.01 (released 2026-04-27) hardened the BSD-style
ar symbol-table parse path and the Microsoft .lib second-linker
file parse path in two ways:

1. BSD ar: the read of the 4-byte `namesSize` field from
   `p + namesStart` lacked a prior bound on
   `namesStart + 4 <= size`. The previous check
   `namesStart > size || namesStart + namesSize != size`
   was applied AFTER the read, so a crafted .a archive could
   produce a 4-byte OOB read of `p[namesStart..namesStart+3]`
   when `namesStart == size`. 26.01 adds the explicit pre-check
   `if (size - namesStart < 4) continue;` before the read.

2. GNU ar archive symbol table + Microsoft .lib second-linker
   file: index arithmetic `i * 4`, `i * 2`, `index * 4` is
   cast to `(size_t)` to prevent 32-bit integer overflow on
   64-bit platforms where address arithmetic must use 64-bit
   width. With `numSymbols` near 2^30 and `numMembers` near
   2^30, `i * 4` could wrap and address an unintended byte.

Patch matches upstream 7-Zip 26.01 source.

Signed-off-by: tonghuaroot <tonghuaroot@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant