From b80acf58f16339078da5cbee88a322f2450aa2ad Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Mar 2011 01:21:02 +0100 Subject: tar: skip leading / and handle names like abc/..////def -> def (not ///def) function old new delta strip_unsafe_prefix - 105 +105 writeFileToTarball 557 520 -37 get_header_tar 1545 1462 -83 Signed-off-by: Denys Vlasenko --- archival/libarchive/get_header_tar.c | 51 ++++++++++++++++++++--------------- archival/tar.c | 13 ++------- include/archive.h | 52 ++++++++++++++++++------------------ testsuite/tar.tests | 2 +- 4 files changed, 59 insertions(+), 59 deletions(-) diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index 6a1532c86..f73cd338e 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c @@ -18,6 +18,35 @@ typedef uint32_t aliased_uint32_t FIX_ALIASING; typedef off_t aliased_off_t FIX_ALIASING; +const char* FAST_FUNC strip_unsafe_prefix(const char *str) +{ + const char *cp = str; + while (1) { + char *cp2; + if (*cp == '/') { + cp++; + continue; + } + if (strncmp(cp, "/../"+1, 3) == 0) { + cp += 3; + continue; + } + cp2 = strstr(cp, "/../"); + if (!cp2) + break; + cp = cp2 + 4; + } + if (cp != str) { + static smallint warned = 0; + if (!warned) { + warned = 1; + bb_error_msg("removing leading '%.*s' from member names", + (int)(cp - str), str); + } + } + return cp; +} + /* NB: _DESTROYS_ str[len] character! */ static unsigned long long getOctal(char *str, int len) { @@ -424,27 +453,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) #endif /* Everything up to and including last ".." component is stripped */ - cp = file_header->name; - while (1) { - char *cp2; - if (strncmp(cp, "/../"+1, 3) == 0) { - cp += 3; - continue; - } - cp2 = strstr(cp, "/../"); - if (cp2) { - cp = cp2 + 4; - continue; - } - break; - } - if (cp != file_header->name) { - if (!(archive_handle->ah_flags & ARCHIVE_TAR__TRUNC_WARNED)) { - archive_handle->ah_flags |= ARCHIVE_TAR__TRUNC_WARNED; - bb_error_msg("removing leading '%.*s'", (int)(cp - file_header->name), file_header->name); - } - overlapping_strcpy(file_header->name, cp); - } + overlapping_strcpy(file_header->name, strip_unsafe_prefix(file_header->name)); /* Strip trailing '/' in directories */ /* Must be done after mode is set as '/' is used to check if it's a directory */ diff --git a/archival/tar.c b/archival/tar.c index 1e3cecf44..d43c8dee3 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -397,17 +397,8 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb DBG("writeFileToTarball('%s')", fileName); - /* Strip leading '/' (must be before memorizing hardlink's name) */ - header_name = fileName; - while (header_name[0] == '/') { - static smallint warned; - - if (!warned) { - bb_error_msg("removing leading '/' from member names"); - warned = 1; - } - header_name++; - } + /* Strip leading '/' and such (must be before memorizing hardlink's name) */ + header_name = strip_unsafe_prefix(fileName); if (header_name[0] == '\0') return TRUE; diff --git a/include/archive.h b/include/archive.h index 9fc77e542..181c187f7 100644 --- a/include/archive.h +++ b/include/archive.h @@ -118,8 +118,6 @@ typedef struct archive_handle_t { #define ARCHIVE_DONT_RESTORE_PERM (1 << 6) #define ARCHIVE_NUMERIC_OWNER (1 << 7) #define ARCHIVE_O_TRUNC (1 << 8) -/* Archiver specific. */ -#define ARCHIVE_TAR__TRUNC_WARNED (1 << 9) /* POSIX tar Header Block, from POSIX 1003.1-1990 */ @@ -161,37 +159,39 @@ typedef struct unpack_info_t { time_t mtime; } unpack_info_t; -extern archive_handle_t *init_handle(void) FAST_FUNC; +archive_handle_t *init_handle(void) FAST_FUNC; -extern char filter_accept_all(archive_handle_t *archive_handle) FAST_FUNC; -extern char filter_accept_list(archive_handle_t *archive_handle) FAST_FUNC; -extern char filter_accept_list_reassign(archive_handle_t *archive_handle) FAST_FUNC; -extern char filter_accept_reject_list(archive_handle_t *archive_handle) FAST_FUNC; +char filter_accept_all(archive_handle_t *archive_handle) FAST_FUNC; +char filter_accept_list(archive_handle_t *archive_handle) FAST_FUNC; +char filter_accept_list_reassign(archive_handle_t *archive_handle) FAST_FUNC; +char filter_accept_reject_list(archive_handle_t *archive_handle) FAST_FUNC; -extern void unpack_ar_archive(archive_handle_t *ar_archive) FAST_FUNC; +void unpack_ar_archive(archive_handle_t *ar_archive) FAST_FUNC; -extern void data_skip(archive_handle_t *archive_handle) FAST_FUNC; -extern void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC; -extern void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC; -extern void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC; +void data_skip(archive_handle_t *archive_handle) FAST_FUNC; +void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC; +void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC; +void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC; -extern void header_skip(const file_header_t *file_header) FAST_FUNC; -extern void header_list(const file_header_t *file_header) FAST_FUNC; -extern void header_verbose_list(const file_header_t *file_header) FAST_FUNC; +void header_skip(const file_header_t *file_header) FAST_FUNC; +void header_list(const file_header_t *file_header) FAST_FUNC; +void header_verbose_list(const file_header_t *file_header) FAST_FUNC; -extern char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC; -extern char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC; -extern char get_header_tar(archive_handle_t *archive_handle) FAST_FUNC; -extern char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC; -extern char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC; -extern char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC; +char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC; +char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC; +char get_header_tar(archive_handle_t *archive_handle) FAST_FUNC; +char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC; +char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC; +char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC; -extern void seek_by_jump(int fd, off_t amount) FAST_FUNC; -extern void seek_by_read(int fd, off_t amount) FAST_FUNC; +void seek_by_jump(int fd, off_t amount) FAST_FUNC; +void seek_by_read(int fd, off_t amount) FAST_FUNC; -extern void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC; -extern const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC; -extern const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; +const char *strip_unsafe_prefix(const char *str) FAST_FUNC; + +void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC; +const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC; +const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; /* A bit of bunzip2 internals are exposed for compressed help support: */ typedef struct bunzip_data bunzip_data; diff --git a/testsuite/tar.tests b/testsuite/tar.tests index d41d10d57..534135df8 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -178,7 +178,7 @@ rm -rf input_* 2>/dev/null tar -vxf test.tar 2>&1 cat input_dir/file 2>&1 " "\ -tar: removing leading './../tar.tempdir/input_dir/../' +tar: removing leading './../tar.tempdir/input_dir/../' from member names input_dir/ input_dir/file Ok -- cgit v1.2.3