From 8f558b2a79aa00c7a07dda14cd41614accec72f7 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Tue, 22 Aug 2023 15:03:01 +0200 Subject: [PATCH] uudecode filter: in raw mode decode file name and file mode Fixes #1941 --- Makefile.am | 3 + libarchive/archive_read_support_filter_uu.c | 41 +++++++++++- libarchive/test/CMakeLists.txt | 1 + .../test_read_filter_uudecode_base64_raw.uu | 11 +++ .../test/test_read_filter_uudecode_raw.c | 67 +++++++++++++++++++ .../test/test_read_filter_uudecode_raw.uu | 14 ++++ 6 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 libarchive/test/test_read_filter_uudecode_base64_raw.uu create mode 100644 libarchive/test/test_read_filter_uudecode_raw.c create mode 100644 libarchive/test/test_read_filter_uudecode_raw.uu diff --git a/Makefile.am b/Makefile.am index a79afb5cc..42424a233 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/libarchive/archive_read_support_filter_uu.c b/libarchive/archive_read_support_filter_uu.c index 209b2a159..f84a64fb8 100644 --- a/libarchive/archive_read_support_filter_uu.c +++ b/libarchive/archive_read_support_filter_uu.c @@ -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); diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index bbbff2231..5e17d62fd 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -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 index 000000000..b4ddfb0a2 --- /dev/null +++ b/libarchive/test/test_read_filter_uudecode_base64_raw.uu @@ -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 index 000000000..6f02dc5de --- /dev/null +++ b/libarchive/test/test_read_filter_uudecode_raw.c @@ -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 index 000000000..8a5f8b5a6 --- /dev/null +++ b/libarchive/test/test_read_filter_uudecode_raw.uu @@ -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 -- 2.47.2