]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
mtree reader: allow only printable ascii characters
authorMartin Matuska <martin@matuska.org>
Mon, 6 May 2019 23:16:12 +0000 (01:16 +0200)
committerMartin Matuska <martin@matuska.org>
Tue, 7 May 2019 10:18:36 +0000 (12:18 +0200)
libarchive/archive_read_support_format_mtree.c
libarchive/test/test_read_format_mtree.c
libarchive/test/test_read_format_mtree_noprint.mtree.uu [new file with mode: 0644]

index 5b0eadc0844c2a6c0ec848b45ed9e4cbec727c36..a7331a2672c7ad3792f079ec7fba405fff5b71f2 100644 (file)
@@ -45,6 +45,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
 
 #include "archive.h"
 #include "archive_entry.h"
@@ -1011,7 +1014,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
 {
        ssize_t len;
        uintmax_t counter;
-       char *p;
+       char *p, *s;
        struct mtree_option *global;
        struct mtree_entry *last_entry;
        int r, is_form_d;
@@ -1025,6 +1028,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
        (void)detect_form(a, &is_form_d);
 
        for (counter = 1; ; ++counter) {
+               r = ARCHIVE_OK;
                len = readline(a, mtree, &p, 65536);
                if (len == 0) {
                        mtree->this_entry = mtree->entries;
@@ -1045,6 +1049,15 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
                        continue;
                if (*p == '\r' || *p == '\n' || *p == '\0')
                        continue;
+               /* Non-printable characters are not allowed */
+               for (s = p;s < p + len - 1; s++) {
+                       if (!isprint(*s)) {
+                               r = ARCHIVE_FATAL;
+                               break;
+                       }
+               }
+               if (r != ARCHIVE_OK)
+                       break;
                if (*p != '/') {
                        r = process_add_entry(a, mtree, &global, p, len,
                            &last_entry, is_form_d);
index 8576d579f9c637b7cc332dfea16f3d1cf3d5ddb6..df6f6cde0cdb2898b3a7fa802529a85d1db00a64 100644 (file)
@@ -717,4 +717,28 @@ DEFINE_TEST(test_read_format_mtree_nonexistent_contents_file)
        assertEqualInt(ARCHIVE_OK, archive_read_close(a));
        assertEqualInt(ARCHIVE_OK, archive_read_free(a));
 }
+/*
+ * Check mtree file with non-printable ascii characters
+ */
+DEFINE_TEST(test_read_format_mtree_noprint)
+{
+       const char reffile[] = "test_read_format_mtree_noprint.mtree";
+       struct archive_entry *ae;
+       struct archive *a;
 
+       extract_reference_file(reffile);
+
+       assert((a = archive_read_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_read_support_filter_all(a));
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_read_support_format_all(a));
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_read_open_filename(a, reffile, 11));
+
+       assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
+       assertEqualString("Can't parse line 3", archive_error_string(a));
+
+       assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
diff --git a/libarchive/test/test_read_format_mtree_noprint.mtree.uu b/libarchive/test/test_read_format_mtree_noprint.mtree.uu
new file mode 100644 (file)
index 0000000..7965cdf
--- /dev/null
@@ -0,0 +1,4 @@
+begin 644 test_read_format_mtree_noprint.mtree
+K(VUT<F5E"F1I<E]O:R!T>7!E/61I<@ID:7)?P[;%H<2'('1Y<&4]9&ER"@``
+`
+end