[gnome-autoar/wip/oholy/absolute-paths] extractor: Ensure that absolute paths are relative to destination




commit 8bbb2d511cdc93383e73b5d5ae5855a329a7184b
Author: Ondrej Holy <oholy redhat com>
Date:   Thu Jul 8 10:22:58 2021 +0200

    extractor: Ensure that absolute paths are relative to destination
    
    Currently, archive entries with absolute paths lose their paths when
    extracting, or even cause crashes. The code expects that the
    `autoar_extractor_do_sanitize_pathname` function will always return paths
    inside, or equal to the destination directory, but this is not true. The
    problem is that the `g_file_get_child` resp. `g_file_resolve_relative_path`
    functions expect relative paths, but are used with absolute paths also.
    Let's convert absolute paths to relative ones to ensure that they will
    be exctracted as relative to the destination dir. Also, update the
    corresponding test case to confirm this.
    
    Fixes: https://gitlab.gnome.org/GNOME/gnome-autoar/-/issues/32

 gnome-autoar/autoar-extractor.c                     |   7 +++++++
 .../test-sanitize-absolute-path/input/arextract.tar | Bin 10240 -> 10240 bytes
 .../reference/arextract/arextract.txt               |   1 +
 tests/test-extract-unit.c                           |  14 +++++++++-----
 4 files changed, 17 insertions(+), 5 deletions(-)
---
diff --git a/gnome-autoar/autoar-extractor.c b/gnome-autoar/autoar-extractor.c
index c2d4f40..758f741 100644
--- a/gnome-autoar/autoar-extractor.c
+++ b/gnome-autoar/autoar-extractor.c
@@ -885,6 +885,10 @@ autoar_extractor_do_sanitize_pathname (AutoarExtractor *self,
   /* Use output_file when called from autoar_extractor_step_scan_toplevel(). */
   destination = (self->destination_dir != NULL) ? self->destination_dir : self->output_file;
 
+  /* Convert absolute paths to relative */
+  if (g_path_is_absolute (pathname_bytes))
+    pathname_bytes = g_path_skip_root (pathname_bytes);
+
   utf8_pathname = autoar_common_get_utf8_pathname (pathname_bytes);
   extracted_filename = g_file_get_child (destination,
                                          utf8_pathname ?  utf8_pathname : pathname_bytes);
@@ -1800,6 +1804,9 @@ autoar_extractor_step_decide_destination (AutoarExtractor *self)
     GFile *file;
 
     relative_path = g_file_get_relative_path (self->output_file, l->data);
+    if (relative_path == NULL)
+      relative_path = g_strdup ("");
+
     file = g_file_resolve_relative_path (self->destination_dir,
                                          relative_path);
     files = g_list_prepend (files, file);
diff --git a/tests/files/extract/test-sanitize-absolute-path/input/arextract.tar 
b/tests/files/extract/test-sanitize-absolute-path/input/arextract.tar
index b05d66a..3a4a68f 100644
Binary files a/tests/files/extract/test-sanitize-absolute-path/input/arextract.tar and 
b/tests/files/extract/test-sanitize-absolute-path/input/arextract.tar differ
diff --git a/tests/files/extract/test-sanitize-absolute-path/reference/arextract/arextract.txt 
b/tests/files/extract/test-sanitize-absolute-path/reference/arextract/arextract.txt
new file mode 100644
index 0000000..12466e2
--- /dev/null
+++ b/tests/files/extract/test-sanitize-absolute-path/reference/arextract/arextract.txt
@@ -0,0 +1 @@
+AutoarExtract
diff --git a/tests/test-extract-unit.c b/tests/test-extract-unit.c
index 1e7062b..1aa8574 100644
--- a/tests/test-extract-unit.c
+++ b/tests/test-extract-unit.c
@@ -1241,15 +1241,18 @@ static void
 test_sanitize_absolute_path (void)
 {
   /* arextract.tar
-   * └── /arextract.txt
+   * ├── /
+   * ├── /arextract.txt
+   * └── /arextract/arextract.txt
    *
-   * 0 directories, 1 file
+   * 1 directories, 2 file
    *
    *
    * ref
-   * └── arextract.txt
+   * ├── arextract.txt
+   * └── arextract/arextract.txt
    *
-   * 0 directories, 1 file
+   * 1 directories, 2 file
    */
 
   g_autoptr (ExtractTest) extract_test = NULL;
@@ -1267,12 +1270,13 @@ test_sanitize_absolute_path (void)
   archive = g_file_get_child (extract_test->input, "arextract.tar");
 
   extractor = autoar_extractor_new (archive, extract_test->output);
+  autoar_extractor_set_output_is_dest (extractor, TRUE);
 
   data = extract_test_data_new_for_extract (extractor);
 
   autoar_extractor_start (extractor, data->cancellable);
 
-  g_assert_cmpuint (data->number_of_files, ==, 1);
+  g_assert_cmpuint (data->number_of_files, ==, 3);
   g_assert_no_error (data->error);
   g_assert_true (data->completed_signalled);
   assert_reference_and_output_match (extract_test);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]