diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-01-27 19:04:08 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-02-14 17:38:29 +0100 |
commit | 20f02c3c871cf0c8d9d2f2dad11d96c0ea41e0df (patch) | |
tree | b1ea7f4a3e333910b2edc575e99ca1ddecbc1ff3 | |
parent | 277636670c583720580c452e90b73cc2a5b0357e (diff) | |
download | busybox-w32-20f02c3c871cf0c8d9d2f2dad11d96c0ea41e0df.tar.gz busybox-w32-20f02c3c871cf0c8d9d2f2dad11d96c0ea41e0df.tar.bz2 busybox-w32-20f02c3c871cf0c8d9d2f2dad11d96c0ea41e0df.zip |
tar: accomodate non-terminated tar.chksum fields as seen from github.com
function old new delta
get_header_tar 1783 1696 -87
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | archival/libarchive/get_header_tar.c | 49 |
1 files changed, 25 insertions, 24 deletions
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index aeb54190f..5c495e14e 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c | |||
@@ -152,6 +152,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
152 | file_header_t *file_header = archive_handle->file_header; | 152 | file_header_t *file_header = archive_handle->file_header; |
153 | struct tar_header_t tar; | 153 | struct tar_header_t tar; |
154 | char *cp; | 154 | char *cp; |
155 | int tar_typeflag; /* can be "char", "int" seems give smaller code */ | ||
155 | int i, sum_u, sum; | 156 | int i, sum_u, sum; |
156 | #if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY | 157 | #if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY |
157 | int sum_s; | 158 | int sum_s; |
@@ -253,10 +254,10 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
253 | * POSIX says that checksum is done on unsigned bytes, but | 254 | * POSIX says that checksum is done on unsigned bytes, but |
254 | * Sun and HP-UX gets it wrong... more details in | 255 | * Sun and HP-UX gets it wrong... more details in |
255 | * GNU tar source. */ | 256 | * GNU tar source. */ |
257 | sum_u = ' ' * sizeof(tar.chksum); | ||
256 | #if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY | 258 | #if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY |
257 | sum_s = ' ' * sizeof(tar.chksum); | 259 | sum_s = sum_u; |
258 | #endif | 260 | #endif |
259 | sum_u = ' ' * sizeof(tar.chksum); | ||
260 | for (i = 0; i < 148; i++) { | 261 | for (i = 0; i < 148; i++) { |
261 | sum_u += ((unsigned char*)&tar)[i]; | 262 | sum_u += ((unsigned char*)&tar)[i]; |
262 | #if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY | 263 | #if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY |
@@ -269,27 +270,22 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
269 | sum_s += ((signed char*)&tar)[i]; | 270 | sum_s += ((signed char*)&tar)[i]; |
270 | #endif | 271 | #endif |
271 | } | 272 | } |
272 | /* This field does not need special treatment (getOctal) */ | 273 | /* Most tarfiles have tar.chksum NUL or space terminated, but |
273 | { | 274 | * github.com decided to be "special" and have unterminated field: |
274 | char *endp; /* gcc likes temp var for &endp */ | 275 | * 0090: 30343300 30303031 33323731 30000000 |043.000132710...| |
275 | sum = strtoul(tar.chksum, &endp, 8); | 276 | * ^^^^^^^^| |
276 | if ((*endp != '\0' && *endp != ' ') | 277 | * Need to use GET_OCTAL. This overwrites tar.typeflag ---+ |
277 | || (sum_u != sum IF_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum)) | 278 | * (the '0' char immediately after chksum in example above) with NUL. |
278 | ) { | 279 | */ |
279 | bb_error_msg_and_die("invalid tar header checksum"); | 280 | tar_typeflag = (uint8_t)tar.typeflag; /* save it */ |
280 | } | 281 | sum = GET_OCTAL(tar.chksum); |
281 | } | 282 | if (sum_u != sum |
282 | /* don't use xstrtoul, tar.chksum may have leading spaces */ | 283 | IF_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum) |
283 | sum = strtoul(tar.chksum, NULL, 8); | 284 | ) { |
284 | if (sum_u != sum IF_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum)) { | ||
285 | bb_error_msg_and_die("invalid tar header checksum"); | 285 | bb_error_msg_and_die("invalid tar header checksum"); |
286 | } | 286 | } |
287 | 287 | ||
288 | /* 0 is reserved for high perf file, treat as normal file */ | 288 | /* GET_OCTAL trashes subsequent field, therefore we call it |
289 | if (!tar.typeflag) tar.typeflag = '0'; | ||
290 | parse_names = (tar.typeflag >= '0' && tar.typeflag <= '7'); | ||
291 | |||
292 | /* getOctal trashes subsequent field, therefore we call it | ||
293 | * on fields in reverse order */ | 289 | * on fields in reverse order */ |
294 | if (tar.devmajor[0]) { | 290 | if (tar.devmajor[0]) { |
295 | char t = tar.prefix[0]; | 291 | char t = tar.prefix[0]; |
@@ -299,6 +295,11 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
299 | file_header->device = makedev(major, minor); | 295 | file_header->device = makedev(major, minor); |
300 | tar.prefix[0] = t; | 296 | tar.prefix[0] = t; |
301 | } | 297 | } |
298 | |||
299 | /* 0 is reserved for high perf file, treat as normal file */ | ||
300 | if (tar_typeflag == '\0') tar_typeflag = '0'; | ||
301 | parse_names = (tar_typeflag >= '0' && tar_typeflag <= '7'); | ||
302 | |||
302 | file_header->link_target = NULL; | 303 | file_header->link_target = NULL; |
303 | if (!p_linkname && parse_names && tar.linkname[0]) { | 304 | if (!p_linkname && parse_names && tar.linkname[0]) { |
304 | file_header->link_target = xstrndup(tar.linkname, sizeof(tar.linkname)); | 305 | file_header->link_target = xstrndup(tar.linkname, sizeof(tar.linkname)); |
@@ -332,7 +333,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
332 | 333 | ||
333 | /* Set bits 12-15 of the files mode */ | 334 | /* Set bits 12-15 of the files mode */ |
334 | /* (typeflag was not trashed because chksum does not use getOctal) */ | 335 | /* (typeflag was not trashed because chksum does not use getOctal) */ |
335 | switch (tar.typeflag) { | 336 | switch (tar_typeflag) { |
336 | case '1': /* hardlink */ | 337 | case '1': /* hardlink */ |
337 | /* we mark hardlinks as regular files with zero size and a link name */ | 338 | /* we mark hardlinks as regular files with zero size and a link name */ |
338 | file_header->mode |= S_IFREG; | 339 | file_header->mode |= S_IFREG; |
@@ -381,7 +382,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
381 | case 'x': { /* pax extended header */ | 382 | case 'x': { /* pax extended header */ |
382 | if ((uoff_t)file_header->size > 0xfffff) /* paranoia */ | 383 | if ((uoff_t)file_header->size > 0xfffff) /* paranoia */ |
383 | goto skip_ext_hdr; | 384 | goto skip_ext_hdr; |
384 | process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g')); | 385 | process_pax_hdr(archive_handle, file_header->size, (tar_typeflag == 'g')); |
385 | goto again_after_align; | 386 | goto again_after_align; |
386 | #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS | 387 | #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS |
387 | /* See http://www.gnu.org/software/tar/manual/html_node/Extensions.html */ | 388 | /* See http://www.gnu.org/software/tar/manual/html_node/Extensions.html */ |
@@ -419,7 +420,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
419 | skip_ext_hdr: | 420 | skip_ext_hdr: |
420 | { | 421 | { |
421 | off_t sz; | 422 | off_t sz; |
422 | bb_error_msg("warning: skipping header '%c'", tar.typeflag); | 423 | bb_error_msg("warning: skipping header '%c'", tar_typeflag); |
423 | sz = (file_header->size + 511) & ~(off_t)511; | 424 | sz = (file_header->size + 511) & ~(off_t)511; |
424 | archive_handle->offset += sz; | 425 | archive_handle->offset += sz; |
425 | sz >>= 9; /* sz /= 512 but w/o contortions for signed div */ | 426 | sz >>= 9; /* sz /= 512 but w/o contortions for signed div */ |
@@ -429,7 +430,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
429 | goto again_after_align; | 430 | goto again_after_align; |
430 | } | 431 | } |
431 | default: | 432 | default: |
432 | bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag); | 433 | bb_error_msg_and_die("unknown typeflag: 0x%x", tar_typeflag); |
433 | } | 434 | } |
434 | 435 | ||
435 | #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS | 436 | #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS |