diff options
Diffstat (limited to 'archival')
-rw-r--r-- | archival/libarchive/get_header_tar.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index 2e0332792..6a1532c86 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c | |||
@@ -422,11 +422,28 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
422 | p_linkname = NULL; | 422 | p_linkname = NULL; |
423 | } | 423 | } |
424 | #endif | 424 | #endif |
425 | if (strncmp(file_header->name, "/../"+1, 3) == 0 | 425 | |
426 | || strstr(file_header->name, "/../") | 426 | /* Everything up to and including last ".." component is stripped */ |
427 | ) { | 427 | cp = file_header->name; |
428 | bb_error_msg_and_die("name with '..' encountered: '%s'", | 428 | while (1) { |
429 | file_header->name); | 429 | char *cp2; |
430 | if (strncmp(cp, "/../"+1, 3) == 0) { | ||
431 | cp += 3; | ||
432 | continue; | ||
433 | } | ||
434 | cp2 = strstr(cp, "/../"); | ||
435 | if (cp2) { | ||
436 | cp = cp2 + 4; | ||
437 | continue; | ||
438 | } | ||
439 | break; | ||
440 | } | ||
441 | if (cp != file_header->name) { | ||
442 | if (!(archive_handle->ah_flags & ARCHIVE_TAR__TRUNC_WARNED)) { | ||
443 | archive_handle->ah_flags |= ARCHIVE_TAR__TRUNC_WARNED; | ||
444 | bb_error_msg("removing leading '%.*s'", (int)(cp - file_header->name), file_header->name); | ||
445 | } | ||
446 | overlapping_strcpy(file_header->name, cp); | ||
430 | } | 447 | } |
431 | 448 | ||
432 | /* Strip trailing '/' in directories */ | 449 | /* Strip trailing '/' in directories */ |