tar: skip leading / and handle names like abc/..////def -> def (not ///def)
authorDenys Vlasenko <vda.linux@googlemail.com>
Wed, 2 Mar 2011 00:21:02 +0000 (01:21 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Wed, 2 Mar 2011 00:21:02 +0000 (01:21 +0100)
function                                             old     new   delta
strip_unsafe_prefix                                    -     105    +105
writeFileToTarball                                   557     520     -37
get_header_tar                                      1545    1462     -83

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
archival/libarchive/get_header_tar.c
archival/tar.c
include/archive.h
testsuite/tar.tests

index 6a1532c866d19954d526daaa2514c91d848efa1d..f73cd338eb8dd9732e3d8458e97f885c82f852eb 100644 (file)
@@ -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 */
index 1e3cecf44cc2e7c7c006225a06b87ccf11785b98..d43c8dee365c31c3e3fed3eaccdb04ea3dfb594d 100644 (file)
@@ -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;
index 9fc77e542bcdb188309d5251595c5fc51f77c700..181c187f750cafda705949566ed44482ccb66d15 100644 (file)
@@ -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;
index d41d10d5750d4cd08d2909e10b09a37b914e04bf..534135df82baf72e84cd5e671b136baa6d2a56d9 100755 (executable)
@@ -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