The version number lies
The blog demonstrates through binary patch-diffing that Apple silently backported the CVE-2025-5915 heap-buffer-overflow fix from libarchive 3.8.0 into iOS 18.6's libarchive 3.7.4 fork without updating the version string. iOS 18.5 (build 22F76) ships libarchive 3.7.4 without the fix and is vulnerable to a controlled heap over-read of up to ~256 KB via a crafted RAR v4 archive. The root cause is an unchecked blocklength in parse_filter() that allows a RAR-VM filter to request more bytes from the LZSS window than were allocated, leading to out-of-bounds heap read in copy_from_lzss_window(). The same memcpy also had a write-side overflow (CVE-2024-26256) that Apple had already backported into iOS 18.5. The author provides on-device proof on an iPhone 14 running iOS 18.5, demonstrating ~150 KB of heap disclosure through the system libarchive. The article also documents a second independent bug in the same function: a wrap-around memcpy destination error fixed in the same commit.
Research notes
- Root causeThe vulnerability is an unchecked blocklength in parse_filter() that allows a RAR-VM filter to request more bytes from the LZSS window than were allocated via unp_size, leading to an out-of-bounds heap read in copy_from_lzss_window().
- Technical detailApple silently backported the CVE-2025-5915 fix (commit a612bf62) from libarchive 3.8.0 into iOS 18.6's libarchive 3.7.4 fork without updating the version string. The fix adds a guard: if (blocklength > rar->dictionary_size) return 0.
- Technical detailThe same memcpy in copy_from_lzss_window() had two independent overflow paths: a source over-read (CVE-2025-5915) when blocklength exceeds the window, and a destination over-write (CVE-2024-26256) when blocklength exceeds VM_MEMORY_SIZE (0x40000). Apple had already backported the CVE-2024-26256 write-side cap into iOS 18.5.
- PoC researchOn-device proof on iPhone 14 running iOS 18.5 demonstrates ~150 KB of heap disclosure through the system libarchive.2.dylib using a crafted RAR v4 archive with a 32-byte window and blocklength of 0x3C000.
- Technical detailThe fix commit a612bf62 also contains a second independent bug fix: a wrap-around memcpy destination error in copy_from_lzss_window() where the second memcpy overwrote the start of the buffer instead of continuing at buffer + firstpart.