diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-03-02 03:21:02 +0300 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-03-02 03:21:02 +0300 |
commit | b80acf58f16339078da5cbee88a322f2450aa2ad (patch) | |
tree | c542be76efce95b7da793c9736fe92d56afb71c1 /archival/libarchive | |
parent | ea6116ee59af0945f4a6ac9ede984930a0ede429 (diff) |
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 <vda.linux@googlemail.com>
Diffstat (limited to 'archival/libarchive')
-rw-r--r-- | archival/libarchive/get_header_tar.c | 51 |
1 files changed, 30 insertions, 21 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 */ |