]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
uudecode filter: in raw mode decode file name and file mode
authorMartin Matuska <martin.matuska@axelspringer.com>
Tue, 22 Aug 2023 13:03:01 +0000 (15:03 +0200)
committerMartin Matuska <martin.matuska@axelspringer.com>
Tue, 22 Aug 2023 13:15:10 +0000 (15:15 +0200)
Fixes #1941

Makefile.am
libarchive/archive_read_support_filter_uu.c
libarchive/test/CMakeLists.txt
libarchive/test/test_read_filter_uudecode_base64_raw.uu [new file with mode: 0644]
libarchive/test/test_read_filter_uudecode_raw.c [new file with mode: 0644]
libarchive/test/test_read_filter_uudecode_raw.uu [new file with mode: 0644]

index a79afb5cc8c00df1f412a9d29a18ec8a77bc5e27..42424a2334ccb21139d9f7f14ef9d61483e097e0 100644 (file)
@@ -454,6 +454,7 @@ libarchive_test_SOURCES= \
        libarchive/test/test_read_filter_program.c \
        libarchive/test/test_read_filter_program_signature.c \
        libarchive/test/test_read_filter_uudecode.c \
+       libarchive/test/test_read_filter_uudecode_raw.c \
        libarchive/test/test_read_format_7zip.c \
        libarchive/test/test_read_format_7zip_encryption_data.c \
        libarchive/test/test_read_format_7zip_encryption_partially.c \
@@ -748,6 +749,8 @@ libarchive_test_EXTRA_DIST=\
        libarchive/test/test_read_filter_lrzip.tar.lrz.uu \
        libarchive/test/test_read_filter_lzop.tar.lzo.uu \
        libarchive/test/test_read_filter_lzop_multiple_parts.tar.lzo.uu \
+       libarchive/test/test_read_filter_uudecode_raw.uu \
+       libarchive/test/test_read_filter_uudecode_base64_raw.uu \
        libarchive/test/test_read_format_mtree_crash747.mtree.bz2.uu \
        libarchive/test/test_read_format_mtree_noprint.mtree.uu \
        libarchive/test/test_read_format_7zip_bcj2_bzip2.7z.uu \
index 209b2a1593a096a841fcd139fc5fb19195f82259..f84a64fb821b3ecccfd89f295808a76eed43c4a7 100644 (file)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 #endif
 
 #include "archive.h"
+#include "archive_entry.h"
 #include "archive_private.h"
 #include "archive_read_private.h"
 
@@ -57,12 +58,17 @@ struct uudecode {
 #define ST_UUEND       2
 #define ST_READ_BASE64 3
 #define ST_IGNORE      4
+       mode_t          mode;
+       int             mode_set;
+       char            *name;
 };
 
 static int     uudecode_bidder_bid(struct archive_read_filter_bidder *,
                    struct archive_read_filter *filter);
 static int     uudecode_bidder_init(struct archive_read_filter *);
 
+static int     uudecode_read_header(struct archive_read_filter *,
+                   struct archive_entry *entry);
 static ssize_t uudecode_filter_read(struct archive_read_filter *,
                    const void **);
 static int     uudecode_filter_close(struct archive_read_filter *);
@@ -355,6 +361,7 @@ static const struct archive_read_filter_vtable
 uudecode_reader_vtable = {
        .read = uudecode_filter_read,
        .close = uudecode_filter_close,
+       .read_header = uudecode_read_header
 };
 
 static int
@@ -385,6 +392,8 @@ uudecode_bidder_init(struct archive_read_filter *self)
        uudecode->in_allocated = IN_BUFF_SIZE;
        uudecode->out_buff = out_buff;
        uudecode->state = ST_FIND_HEAD;
+       uudecode->mode_set = 0;
+       uudecode->name = NULL;
        self->vtable = &uudecode_reader_vtable;
 
        return (ARCHIVE_OK);
@@ -430,6 +439,22 @@ ensure_in_buff_size(struct archive_read_filter *self,
        return (ARCHIVE_OK);
 }
 
+static int
+uudecode_read_header(struct archive_read_filter *self, struct archive_entry *entry)
+{
+
+       struct uudecode *uudecode;
+       uudecode = (struct uudecode *)self->data;
+
+       if (uudecode->mode_set != 0)
+               archive_entry_set_mode(entry, S_IFREG | uudecode->mode);
+
+       if (uudecode->name != NULL)
+               archive_entry_set_pathname(entry, uudecode->name);
+
+       return (ARCHIVE_OK);
+}
+
 static ssize_t
 uudecode_filter_read(struct archive_read_filter *self, const void **buff)
 {
@@ -439,7 +464,7 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff)
        ssize_t avail_in, ravail;
        ssize_t used;
        ssize_t total;
-       ssize_t len, llen, nl;
+       ssize_t len, llen, nl, namelen;
 
        uudecode = (struct uudecode *)self->data;
 
@@ -544,6 +569,19 @@ read_more:
                                        uudecode->state = ST_READ_UU;
                                else
                                        uudecode->state = ST_READ_BASE64;
+                               uudecode->mode = (mode_t)(
+                                   ((int)(b[l] - '0') * 64) +
+                                   ((int)(b[l+1] - '0') * 8) +
+                                    (int)(b[l+2] - '0'));
+                               uudecode->mode_set = 1;
+                               namelen = len - l - 4;
+                               if (namelen > 1) {
+                                       uudecode->name = malloc(namelen);
+                                       strncpy(uudecode->name,
+                                           (const char *)(b + l + 4),
+                                           namelen);
+                                       uudecode->name[namelen] = '\0';
+                               }
                        }
                        break;
                case ST_READ_UU:
@@ -676,6 +714,7 @@ uudecode_filter_close(struct archive_read_filter *self)
        uudecode = (struct uudecode *)self->data;
        free(uudecode->in_buff);
        free(uudecode->out_buff);
+       free(uudecode->name);
        free(uudecode);
 
        return (ARCHIVE_OK);
index bbbff2231afe3973f765a051b61096e5b3e5962b..5e17d62fda99be7bed1ae76b1e0c697f3203a0f9 100644 (file)
@@ -98,6 +98,7 @@ IF(ENABLE_TEST)
     test_read_filter_program.c
     test_read_filter_program_signature.c
     test_read_filter_uudecode.c
+    test_read_filter_uudecode_raw.c
     test_read_format_7zip.c
     test_read_format_7zip_encryption_data.c
     test_read_format_7zip_encryption_header.c
diff --git a/libarchive/test/test_read_filter_uudecode_base64_raw.uu b/libarchive/test/test_read_filter_uudecode_base64_raw.uu
new file mode 100644 (file)
index 0000000..b4ddfb0
--- /dev/null
@@ -0,0 +1,11 @@
+begin-base64 600 LICENSE2.txt
+VEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIOKAnEFTIElT4oCdLCBXSVRIT1VUIFdBUlJBTlRZIE9G
+IEFOWSBLSU5ELCBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQg
+VE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJ
+Q1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUg
+QVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFN
+QUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNU
+LCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElP
+TiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBT
+T0ZUV0FSRS4K
+====
diff --git a/libarchive/test/test_read_filter_uudecode_raw.c b/libarchive/test/test_read_filter_uudecode_raw.c
new file mode 100644 (file)
index 0000000..6f02dc5
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2023 Martin Matuska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+DEFINE_TEST(test_read_filter_uudecode_raw)
+{
+        struct archive_entry *ae;
+        struct archive *a;
+
+       const char *name = "test_read_filter_uudecode_raw.uu";
+
+        assert((a = archive_read_new()) != NULL);
+        assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+        assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a));
+        copy_reference_file(name);
+        assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 670));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("LICENSE.txt", archive_entry_pathname(ae));
+       assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae));
+       assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+       assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+DEFINE_TEST(test_read_filter_uudecode_base64_raw)
+{
+        struct archive_entry *ae;
+        struct archive *a;
+
+       const char *name = "test_read_filter_uudecode_base64_raw.uu";
+
+        assert((a = archive_read_new()) != NULL);
+        assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+        assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a));
+        copy_reference_file(name);
+        assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 670));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("LICENSE2.txt", archive_entry_pathname(ae));
+       assertEqualInt((AE_IFREG | 0600), archive_entry_mode(ae));
+       assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+       assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
diff --git a/libarchive/test/test_read_filter_uudecode_raw.uu b/libarchive/test/test_read_filter_uudecode_raw.uu
new file mode 100644 (file)
index 0000000..8a5f8b5
--- /dev/null
@@ -0,0 +1,14 @@
+begin 755 LICENSE.txt
+M5$A%(%-/1E1705)%($E3(%!23U9)1$5$(.*`G$%3($E3XH"=+"!7251(3U54
+M(%=!4E)!3E19($]&($%.62!+24Y$+"!%6%!215-3($]2($E-4$Q)140L($E.
+M0TQ51$E.1R!"550@3D]4($Q)34E4140@5$\@5$A%(%=!4E)!3E1)15,@3T8@
+M34520TA!3E1!0DE,2519+"!&251.15-3($9/4B!!(%!!4E1)0U5,05(@4%52
+M4$]312!!3D0@3D].24Y&4DE.1T5-14Y4+B!)3B!.3R!%5D5.5"!32$%,3"!4
+M2$4@05542$]24R!/4B!#3U!94DE'2%0@2$],1$524R!"12!,24%"3$4@1D]2
+M($%.62!#3$%)32P@1$%-04=%4R!/4B!/5$A%4B!,24%"24Q)5%DL(%=(151(
+M15(@24X@04X@04-424].($]&($-/3E1204-4+"!43U)4($]2($]42$525TE3
+M12P@05))4TE.1R!&4D]-+"!/550@3T8@3U(@24X@0T].3D5#5$E/3B!7251(
+M(%1(12!33T945T%212!/4B!42$4@55-%($]2($]42$52($1%04Q)3D=3($E.
+/(%1(12!33T945T%212X*
+`
+end