From 0fd1bfdbb81dddeb2329137315ce17684a6602c2 Mon Sep 17 00:00:00 2001
From: peijiankang <peijiankang@kylinos.cn>
Date: Thu, 29 Feb 2024 10:34:25 +0800
Subject: [PATCH] CVE-2023-52076

---
 backend/epub/epub-document.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/backend/epub/epub-document.c b/backend/epub/epub-document.c
index c0fa275..b0d42a3 100644
--- a/backend/epub/epub-document.c
+++ b/backend/epub/epub-document.c
@@ -653,7 +653,7 @@ check_mime_type(const gchar* uri,GError** error)
 }
 
 static gboolean
-extract_one_file(EpubDocument* epub_document,GError ** error)
+extract_one_file(EpubDocument* epub_document, GFile *tmp_gfile, GError ** error)
 {
     GFile * outfile ;
     gsize writesize = 0;
@@ -680,6 +680,20 @@ extract_one_file(EpubDocument* epub_document,GError ** error)
     gfilepath = g_string_new(epub_document->tmp_archive_dir) ;
     g_string_append_printf(gfilepath,"/%s",(gchar*)currentfilename);
 
+    outfile = g_file_new_for_path (gfilepath->str);
+    g_autofree gchar *rpath = g_file_get_relative_path (tmp_gfile, outfile);
+
+    if (rpath == NULL)
+    {
+        g_set_error_literal (error,
+                             EV_DOCUMENT_ERROR,
+                             EV_DOCUMENT_ERROR_INVALID,
+                             _("epub file is invalid or corrupt"));
+        g_critical ("Invalid filename in Epub container - '%s'", (gchar *) currentfilename);
+        result = FALSE;
+        goto out;
+    }
+
     /*if we encounter a directory, make a directory inside our temporary folder.*/
     if (directory != NULL && *directory == '\0')
     {
@@ -707,7 +721,6 @@ extract_one_file(EpubDocument* epub_document,GError ** error)
 		g_string_free(dir_create,TRUE);
     }
 
-    outfile = g_file_new_for_path(gfilepath->str);
     outstream = g_file_create(outfile,G_FILE_CREATE_PRIVATE,NULL,error);
     gpointer buffer = g_malloc0(512);
     while ( (writesize = unzReadCurrentFile(epub_document->epubDocument,buffer,512) ) != 0 )
@@ -720,10 +733,10 @@ extract_one_file(EpubDocument* epub_document,GError ** error)
     }
     g_free(buffer);
     g_output_stream_close((GOutputStream*)outstream,NULL,error);
-    g_object_unref(outfile) ;
     g_object_unref(outstream) ;
 
 out:
+    g_object_unref(outfile) ;
     unzCloseCurrentFile (epub_document->epubDocument) ;
     g_string_free(gfilepath,TRUE);
     g_free(currentfilename);
@@ -735,6 +748,7 @@ extract_epub_from_container (const gchar* uri,
                              EpubDocument *epub_document,
                              GError ** error)
 {
+    GFile *tmp_gfile = NULL;
     GError *err = NULL;
     epub_document->archivename = g_filename_from_uri(uri,NULL,error);
 
@@ -796,9 +810,10 @@ extract_epub_from_container (const gchar* uri,
         goto out;
     }
 
+    tmp_gfile = g_file_new_for_path (epub_document->tmp_archive_dir);
     while ( TRUE )
     {
-        if ( extract_one_file(epub_document,&err) == FALSE )
+        if ( extract_one_file(epub_document, tmp_gfile, &err) == FALSE )
         {
             if (err) {
                 g_propagate_error (error, err);
@@ -819,6 +834,7 @@ extract_epub_from_container (const gchar* uri,
     }
 
 out:
+    g_clear_object (&tmp_gfile);
     unzClose(epub_document->epubDocument);
     return result;
 }
-- 
2.41.0

