tar: on extract, everything up to and including last ".." is stripped
No binary (build failed)
—
(log yok)
| @@ -422,11 +422,28 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |
| p_linkname = NULL; | |
| } | |
| #endif | |
| - | if (strncmp(file_header->name, "/../"+1, 3) == 0 |
| - | || strstr(file_header->name, "/../") |
| - | ) { |
| - | bb_error_msg_and_die("name with '..' encountered: '%s'", |
| - | file_header->name); |
| + | |
| + | /* 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); |
| } | |
| /* Strip trailing '/' in directories */ | |
| @@ -118,6 +118,8 @@ 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 */ | |
| @@ -168,6 +168,23 @@ Ok | |
| " \ | |
| "" "" | |
| + | # On extract, everything up to and including last ".." component is stripped |
| + | testing "tar strips /../ on extract" "\ |
| + | rm -rf input_* test.tar 2>/dev/null |
| + | mkdir input_dir |
| + | echo Ok >input_dir/file |
| + | tar cf test.tar ./../tar.tempdir/input_dir/../input_dir 2>&1 |
| + | 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/../' |
| + | input_dir/ |
| + | input_dir/file |
| + | Ok |
| + | " \ |
| + | "" "" |
| + | |
| cd .. && rm -rf tar.tempdir || exit 1 | |