(CVE-2025-6196) New Security Issue
Original reporter: Security Vulnerability Report: Integer Overflow in libgepub EPUB Parser
Area: Platform component (libraries, tools)
Message
Summary
A critical integer overflow vulnerability has been identified in libgepub's EPUB archive handling code. When processing specially crafted EPUB files, the gepub_archive_read_entry() function mishandles file size values, resulting in integer overflows that lead to massive memory allocation attempts and application crashes. This represents a potential denial of service vulnerability.
Vulnerability Details
Vulnerability Type: Integer Overflow / Type Mismatch
Affected Component: gepub-archive.c in libgepub
Severity: High
Exploitability: Medium
The vulnerability stems from a type mismatch between the 64-bit value returned by archive_entry_size() and the 32-bit gint variable used to store it in gepub_archive_read_entry(). When processing large or malformed EPUB files, this mismatch can cause the size value to be truncated and potentially become negative. When this negative value is passed to g_malloc0(), it's interpreted as a massive positive value due to signed-to-unsigned conversion, resulting in allocation failures and application crashes.
Technical Analysis
Vulnerable Code
The vulnerability is in gepub_archive_read_entry() in gepub-archive.c:
GBytes *
gepub_archive_read_entry (GepubArchive *archive,
const gchar *path)
{
struct archive_entry *entry;
guchar *buffer;
gint size; // 32-bit integer
const gchar *_path;
//
size = archive_entry_size (entry); // Returns 64-bit integer
buffer = g_malloc0 (size); // Treats size as unsigned
archive_read_data (archive->archive, buffer, size);
gepub_archive_close (archive);
return g_bytes_new_take (buffer, size);
}
The function archive_entry_size() is defined in libarchive's archive_entry.h as:
__LA_DECL la_int64_t archive_entry_size(struct archive_entry *);
And implemented in libarchive as:
la_int64_t
archive_entry_size(struct archive_entry *entry)
{
return (entry->ae_stat.aest_size);
}
Crash Analysis
When a specially crafted EPUB file is processed, the following crash occurs:
DEBUG: Starting with file: findings_backup/slave05/crashes/id:000001,sig:05,src:000043,time:20841593,execs:31927516,op:havoc,rep:64
DEBUG: About to call gepub_doc_new
==1122360==WARNING: AddressSanitizer failed to allocate 0xfffffffff3ff0117 bytes
(process:1122360): GLib-ERROR **: 04:18:52.636: ../../../glib/gmem.c:139: failed to allocate 18446744073508159767 bytes
The AddressSanitizer output shows an attempt to allocate 0xfffffffff3ff0117 bytes (approximately 18.4 quintillion bytes), which fails as expected.
Stack Trace
The GDB backtrace reveals the exact sequence leading to the crash:
#0 g_log_structured_array [...]
#1 0x00007ffff77193cc in g_log_default_handler [...]
#2 0x00007ffff7719670 in g_logv [...]
#3 0x00007ffff7719953 in g_log [...]
#4 0x00007ffff771a7d5 in g_malloc0 (n_bytes=18446744073508159767) at ../../../glib/gmem.c:138
#5 0x00007ffff7fa69e2 in gepub_archive_read_entry
(archive=0x504000021c50, path=0x7ffff7fad00d "META-INF/container.xml") at ../libgepub/gepub-archive.c:157
entry = 0x51a000000080
buffer = 0x508000002020 "2402"
size = -201391849
_path = 0x7ffff7fad00d "META-INF/container.xml"
#6 0x00007ffff7fa6a8f in gepub_archive_get_root_file (archive=0x504000021c50) at ../libgepub/gepub-archive.c:176
doc = 0x0
root_element = 0x0
root_node = 0x0
bytes = 0x50b000000ca0
buffer = 0x508000002020 "2402"
bufsize = 140737488346704
#7 0x00007ffff7fa7351 in gepub_doc_initable_init [...] at ../libgepub/gepub-doc.c:211
#8 0x00007ffff71c58bc in g_initable_new_valist [...]
#9 0x00007ffff71c59ab in g_initable_new [...]
#10 0x00007ffff7fa756a in gepub_doc_new [...]
#11 0x00005555555565f4 in main (argc=2, argv=0x7fffffffe1e8) at simple_debug_fuzzer.c:39
The key issue is visible in frame Teams/Releng/security#5, where size = -201391849. This negative value occurs due to the truncation of a 64-bit value to 32 bits. When passed to g_malloc0(), this negative value is treated as an unsigned value, resulting in an attempt to allocate approximately 18.4 quintillion bytes.
Reproduction
The vulnerability can be reproduced using the following steps:
- Obtain the crash file:
findings_backup/slave05/crashes/id:000001,sig:05,src:000043,time:20841593,execs:31927516,op:havoc,rep:64 - Build a debug version of gepub with Address Sanitizer enabled
- Run:
./simple_debug_fuzzer_asan
Impact
This vulnerability can be exploited to cause denial of service by crafting EPUB files that trigger excessive memory allocation attempts. When such files are opened by applications using libgepub, they will crash due to memory allocation failures.
Additionally, in certain contexts, integer overflows can sometimes lead to more severe vulnerabilities such as buffer overflows or heap corruption if the allocation succeeds with a truncated size.
Remediation
The recommended fix is to:
- Change the type of
sizeingepub_archive_read_entry()fromginttogint64orgoffsetto properly handle 64-bit values - Add validation to ensure the size is reasonable before allocation:
gint64 size; // Instead of gint size
size = archive_entry_size(entry);
// Validate size
if (size G_MAXSIZE) {
gepub_archive_close(archive);
return NULL;
}
// Allocate buffer with additional error handling
buffer = g_malloc0(size);
if (!buffer) {
gepub_archive_close(archive);
return NULL;
}
Conclusion
This vulnerability highlights the importance of proper type handling and input validation when processing potentially malicious files. Integer overflow vulnerabilities can be subtle but have significant security implications. All applications using libgepub should be updated once a fix is available.