From bce768482f885024d5abee8d5326a170db741552 Mon Sep 17 00:00:00 2001 From: Maximilian Heise <7600641+maxheise@users.noreply.github.com> Date: Thu, 21 May 2026 10:05:56 +0200 Subject: [PATCH] epub: avoid a fixed-size buffer when copying the content path prefix In get_uri_to_content() the directory part of the OPF path is copied into a fixed buffer with a hand-written loop that runs until the last '/', with no bound on how much it copies. The string copied is relativepath, the full-path attribute read from the EPUB's META-INF/container.xml, so its length is whatever the file declares. Two things about the allocation also stand out. The element size is sizeof(gchar*), the size of a pointer (8 bytes on 64-bit), but the buffer holds a string of gchar, i.e. characters, not pointers; the size that matches the data is sizeof(gchar) (1 byte) or simply a byte count, so the '*' is the wrong type for what is stored and the buffer is ~800 bytes only by accident. And 100 is a magic number with no explanation for why it is 100. Because the copy loop is unbounded, the buffer's correctness rests on those accidents. Normal EPUBs use short OPF paths and are unaffected, but a file with a long enough full-path would copy past the buffer. And if someone corrected the type mismatch, sizeof(gchar*) to sizeof(gchar), the buffer would shrink to 100 bytes and the same loop would write past the end on ordinary paths. Compute the prefix length as the distance to the last '/' and use g_strndup(), which allocates a buffer sized to the data and NUL-terminates it, so the copy stays in bounds. This also removes the magic number, the wrong-typed sizeof, and the hand-written loop, and produces the same string. The freeing of the result is unchanged. --- backend/epub/epub-document.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/backend/epub/epub-document.c b/backend/epub/epub-document.c index 57d626c4..c78e0a4a 100644 --- a/backend/epub/epub-document.c +++ b/backend/epub/epub-document.c @@ -921,15 +921,8 @@ get_uri_to_content(const gchar* uri,GError ** error,EpubDocument *epub_document) gchar* documentfolder = g_strrstr((gchar*)relativepath,"/"); if (documentfolder != NULL) { - gchar* copybuffer = (gchar*)relativepath ; - gchar* directorybuffer = g_malloc0(sizeof(gchar*)*100); - gchar* writer = directorybuffer; - - while(copybuffer != documentfolder) { - (*writer) = (*copybuffer); - writer++;copybuffer++; - } - *writer = '\0'; + gsize dir_len = documentfolder - (gchar *) relativepath; + gchar *directorybuffer = g_strndup ((gchar *) relativepath, dir_len); GString *documentdir = g_string_new(tmp_archive_dir); g_string_append_printf(documentdir,"/%s",directorybuffer);