diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-03-02 01:21:02 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-03-02 01:21:02 +0100 |
commit | b80acf58f16339078da5cbee88a322f2450aa2ad (patch) | |
tree | c542be76efce95b7da793c9736fe92d56afb71c1 | |
parent | ea6116ee59af0945f4a6ac9ede984930a0ede429 (diff) | |
download | busybox-w32-b80acf58f16339078da5cbee88a322f2450aa2ad.tar.gz busybox-w32-b80acf58f16339078da5cbee88a322f2450aa2ad.tar.bz2 busybox-w32-b80acf58f16339078da5cbee88a322f2450aa2ad.zip |
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>
-rw-r--r-- | archival/libarchive/get_header_tar.c | 51 | ||||
-rw-r--r-- | archival/tar.c | 13 | ||||
-rw-r--r-- | include/archive.h | 52 | ||||
-rwxr-xr-x | 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; | |||
18 | typedef off_t aliased_off_t FIX_ALIASING; | 18 | typedef off_t aliased_off_t FIX_ALIASING; |
19 | 19 | ||
20 | 20 | ||
21 | const char* FAST_FUNC strip_unsafe_prefix(const char *str) | ||
22 | { | ||
23 | const char *cp = str; | ||
24 | while (1) { | ||
25 | char *cp2; | ||
26 | if (*cp == '/') { | ||
27 | cp++; | ||
28 | continue; | ||
29 | } | ||
30 | if (strncmp(cp, "/../"+1, 3) == 0) { | ||
31 | cp += 3; | ||
32 | continue; | ||
33 | } | ||
34 | cp2 = strstr(cp, "/../"); | ||
35 | if (!cp2) | ||
36 | break; | ||
37 | cp = cp2 + 4; | ||
38 | } | ||
39 | if (cp != str) { | ||
40 | static smallint warned = 0; | ||
41 | if (!warned) { | ||
42 | warned = 1; | ||
43 | bb_error_msg("removing leading '%.*s' from member names", | ||
44 | (int)(cp - str), str); | ||
45 | } | ||
46 | } | ||
47 | return cp; | ||
48 | } | ||
49 | |||
21 | /* NB: _DESTROYS_ str[len] character! */ | 50 | /* NB: _DESTROYS_ str[len] character! */ |
22 | static unsigned long long getOctal(char *str, int len) | 51 | static unsigned long long getOctal(char *str, int len) |
23 | { | 52 | { |
@@ -424,27 +453,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
424 | #endif | 453 | #endif |
425 | 454 | ||
426 | /* Everything up to and including last ".." component is stripped */ | 455 | /* Everything up to and including last ".." component is stripped */ |
427 | cp = file_header->name; | 456 | overlapping_strcpy(file_header->name, strip_unsafe_prefix(file_header->name)); |
428 | while (1) { | ||
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); | ||
447 | } | ||
448 | 457 | ||
449 | /* Strip trailing '/' in directories */ | 458 | /* Strip trailing '/' in directories */ |
450 | /* Must be done after mode is set as '/' is used to check if it's a directory */ | 459 | /* 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 | |||
397 | 397 | ||
398 | DBG("writeFileToTarball('%s')", fileName); | 398 | DBG("writeFileToTarball('%s')", fileName); |
399 | 399 | ||
400 | /* Strip leading '/' (must be before memorizing hardlink's name) */ | 400 | /* Strip leading '/' and such (must be before memorizing hardlink's name) */ |
401 | header_name = fileName; | 401 | header_name = strip_unsafe_prefix(fileName); |
402 | while (header_name[0] == '/') { | ||
403 | static smallint warned; | ||
404 | |||
405 | if (!warned) { | ||
406 | bb_error_msg("removing leading '/' from member names"); | ||
407 | warned = 1; | ||
408 | } | ||
409 | header_name++; | ||
410 | } | ||
411 | 402 | ||
412 | if (header_name[0] == '\0') | 403 | if (header_name[0] == '\0') |
413 | return TRUE; | 404 | 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 { | |||
118 | #define ARCHIVE_DONT_RESTORE_PERM (1 << 6) | 118 | #define ARCHIVE_DONT_RESTORE_PERM (1 << 6) |
119 | #define ARCHIVE_NUMERIC_OWNER (1 << 7) | 119 | #define ARCHIVE_NUMERIC_OWNER (1 << 7) |
120 | #define ARCHIVE_O_TRUNC (1 << 8) | 120 | #define ARCHIVE_O_TRUNC (1 << 8) |
121 | /* Archiver specific. */ | ||
122 | #define ARCHIVE_TAR__TRUNC_WARNED (1 << 9) | ||
123 | 121 | ||
124 | 122 | ||
125 | /* POSIX tar Header Block, from POSIX 1003.1-1990 */ | 123 | /* POSIX tar Header Block, from POSIX 1003.1-1990 */ |
@@ -161,37 +159,39 @@ typedef struct unpack_info_t { | |||
161 | time_t mtime; | 159 | time_t mtime; |
162 | } unpack_info_t; | 160 | } unpack_info_t; |
163 | 161 | ||
164 | extern archive_handle_t *init_handle(void) FAST_FUNC; | 162 | archive_handle_t *init_handle(void) FAST_FUNC; |
165 | 163 | ||
166 | extern char filter_accept_all(archive_handle_t *archive_handle) FAST_FUNC; | 164 | char filter_accept_all(archive_handle_t *archive_handle) FAST_FUNC; |
167 | extern char filter_accept_list(archive_handle_t *archive_handle) FAST_FUNC; | 165 | char filter_accept_list(archive_handle_t *archive_handle) FAST_FUNC; |
168 | extern char filter_accept_list_reassign(archive_handle_t *archive_handle) FAST_FUNC; | 166 | char filter_accept_list_reassign(archive_handle_t *archive_handle) FAST_FUNC; |
169 | extern char filter_accept_reject_list(archive_handle_t *archive_handle) FAST_FUNC; | 167 | char filter_accept_reject_list(archive_handle_t *archive_handle) FAST_FUNC; |
170 | 168 | ||
171 | extern void unpack_ar_archive(archive_handle_t *ar_archive) FAST_FUNC; | 169 | void unpack_ar_archive(archive_handle_t *ar_archive) FAST_FUNC; |
172 | 170 | ||
173 | extern void data_skip(archive_handle_t *archive_handle) FAST_FUNC; | 171 | void data_skip(archive_handle_t *archive_handle) FAST_FUNC; |
174 | extern void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC; | 172 | void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC; |
175 | extern void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC; | 173 | void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC; |
176 | extern void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC; | 174 | void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC; |
177 | 175 | ||
178 | extern void header_skip(const file_header_t *file_header) FAST_FUNC; | 176 | void header_skip(const file_header_t *file_header) FAST_FUNC; |
179 | extern void header_list(const file_header_t *file_header) FAST_FUNC; | 177 | void header_list(const file_header_t *file_header) FAST_FUNC; |
180 | extern void header_verbose_list(const file_header_t *file_header) FAST_FUNC; | 178 | void header_verbose_list(const file_header_t *file_header) FAST_FUNC; |
181 | 179 | ||
182 | extern char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC; | 180 | char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC; |
183 | extern char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC; | 181 | char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC; |
184 | extern char get_header_tar(archive_handle_t *archive_handle) FAST_FUNC; | 182 | char get_header_tar(archive_handle_t *archive_handle) FAST_FUNC; |
185 | extern char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC; | 183 | char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC; |
186 | extern char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC; | 184 | char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC; |
187 | extern char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC; | 185 | char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC; |
188 | 186 | ||
189 | extern void seek_by_jump(int fd, off_t amount) FAST_FUNC; | 187 | void seek_by_jump(int fd, off_t amount) FAST_FUNC; |
190 | extern void seek_by_read(int fd, off_t amount) FAST_FUNC; | 188 | void seek_by_read(int fd, off_t amount) FAST_FUNC; |
191 | 189 | ||
192 | extern void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC; | 190 | const char *strip_unsafe_prefix(const char *str) FAST_FUNC; |
193 | extern const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC; | 191 | |
194 | extern const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; | 192 | void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC; |
193 | const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC; | ||
194 | const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; | ||
195 | 195 | ||
196 | /* A bit of bunzip2 internals are exposed for compressed help support: */ | 196 | /* A bit of bunzip2 internals are exposed for compressed help support: */ |
197 | typedef struct bunzip_data bunzip_data; | 197 | 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 | |||
178 | tar -vxf test.tar 2>&1 | 178 | tar -vxf test.tar 2>&1 |
179 | cat input_dir/file 2>&1 | 179 | cat input_dir/file 2>&1 |
180 | " "\ | 180 | " "\ |
181 | tar: removing leading './../tar.tempdir/input_dir/../' | 181 | tar: removing leading './../tar.tempdir/input_dir/../' from member names |
182 | input_dir/ | 182 | input_dir/ |
183 | input_dir/file | 183 | input_dir/file |
184 | Ok | 184 | Ok |