diff --git a/contrib/libarchive/cpio/cpio.c b/contrib/libarchive/cpio/cpio.c index 18fd72217c1c..3d5a6a837407 100644 --- a/contrib/libarchive/cpio/cpio.c +++ b/contrib/libarchive/cpio/cpio.c @@ -737,7 +737,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath) */ destpath = srcpath; if (cpio->destdir) { - len = strlen(cpio->destdir) + strlen(srcpath) + 8; + len = cpio->destdir_len + strlen(srcpath) + 8; if (len >= cpio->pass_destpath_alloc) { while (len >= cpio->pass_destpath_alloc) { cpio->pass_destpath_alloc += 512; @@ -1228,15 +1228,14 @@ mode_pass(struct cpio *cpio, const char *destdir) struct lafe_line_reader *lr; const char *p; int r; - size_t destdir_len; /* Ensure target dir has a trailing '/' to simplify path surgery. */ - destdir_len = strlen(destdir); - cpio->destdir = malloc(destdir_len + 8); - memcpy(cpio->destdir, destdir, destdir_len); - if (destdir_len == 0 || destdir[destdir_len - 1] != '/') - cpio->destdir[destdir_len++] = '/'; - cpio->destdir[destdir_len++] = '\0'; + cpio->destdir_len = strlen(destdir); + cpio->destdir = malloc(cpio->destdir_len + 8); + memcpy(cpio->destdir, destdir, cpio->destdir_len); + if (cpio->destdir_len == 0 || destdir[cpio->destdir_len - 1] != '/') + cpio->destdir[cpio->destdir_len++] = '/'; + cpio->destdir[cpio->destdir_len] = '\0'; cpio->archive = archive_write_disk_new(); if (cpio->archive == NULL) diff --git a/contrib/libarchive/cpio/cpio.h b/contrib/libarchive/cpio/cpio.h index b10f387be0e3..cd789b580f8e 100644 --- a/contrib/libarchive/cpio/cpio.h +++ b/contrib/libarchive/cpio/cpio.h @@ -64,6 +64,7 @@ struct cpio { int option_numeric_uid_gid; /* -n */ int option_rename; /* -r */ char *destdir; + size_t destdir_len; size_t pass_destpath_alloc; char *pass_destpath; int uid_override; diff --git a/contrib/libarchive/cpio/test/test_format_newc.c b/contrib/libarchive/cpio/test/test_format_newc.c index aa1a9bbb88d8..6b9ba47cfe1a 100644 --- a/contrib/libarchive/cpio/test/test_format_newc.c +++ b/contrib/libarchive/cpio/test/test_format_newc.c @@ -49,10 +49,11 @@ is_hex(const char *p, size_t l) return (1); } -static int +/* Convert up to 8 hex characters to unsigned 32-bit decimal integer */ +static uint32_t from_hex(const char *p, size_t l) { - int r = 0; + uint32_t r = 0; while (l > 0) { r *= 16; @@ -82,11 +83,11 @@ DEFINE_TEST(test_format_newc) { FILE *list; int r; - int devmajor, devminor, ino, gid; - int uid = -1; + uint32_t devmajor, devminor, ino, gid, uid; time_t t, t2, now; char *p, *e; - size_t s, fs, ns; + size_t s; + uint64_t fs, ns; char result[1024]; assertUmask(0); @@ -199,9 +200,11 @@ DEFINE_TEST(test_format_newc) #else assertEqualInt(0x81a4, from_hex(e + 14, 8)); /* Mode */ #endif - if (uid < 0) - uid = from_hex(e + 22, 8); +#if defined(_WIN32) + uid = from_hex(e + 22, 8); +#else assertEqualInt(from_hex(e + 22, 8), uid); /* uid */ +#endif gid = from_hex(e + 30, 8); /* gid */ assertEqualMem(e + 38, "00000003", 8); /* nlink */ t = from_hex(e + 46, 8); /* mtime */ @@ -215,14 +218,14 @@ DEFINE_TEST(test_format_newc) " first appearance should be empty, so this file size\n" " field should be zero"); assertEqualInt(0, from_hex(e + 54, 8)); /* File size */ - fs = from_hex(e + 54, 8); + fs = (uint64_t)from_hex(e + 54, 8); fs += PAD(fs, 4); devmajor = from_hex(e + 62, 8); /* devmajor */ devminor = from_hex(e + 70, 8); /* devminor */ assert(is_hex(e + 78, 8)); /* rdevmajor */ assert(is_hex(e + 86, 8)); /* rdevminor */ assertEqualMem(e + 94, "00000006", 8); /* Name size */ - ns = from_hex(e + 94, 8); + ns = (uint64_t)from_hex(e + 94, 8); ns += PAD(ns + 2, 4); assertEqualInt(0, from_hex(e + 102, 8)); /* check field */ assertEqualMem(e + 110, "file1\0", 6); /* Name contents */ @@ -249,14 +252,14 @@ DEFINE_TEST(test_format_newc) " at t2=%#08jx", (intmax_t)t, (intmax_t)t2); assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */ assertEqualMem(e + 54, "00000005", 8); /* File size */ - fs = from_hex(e + 54, 8); + fs = (uint64_t)from_hex(e + 54, 8); fs += PAD(fs, 4); assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */ assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */ assert(is_hex(e + 78, 8)); /* rdevmajor */ assert(is_hex(e + 86, 8)); /* rdevminor */ assertEqualMem(e + 94, "00000008", 8); /* Name size */ - ns = from_hex(e + 94, 8); + ns = (uint64_t)from_hex(e + 94, 8); ns += PAD(ns + 2, 4); assertEqualInt(0, from_hex(e + 102, 8)); /* check field */ assertEqualMem(e + 110, "symlink\0\0\0", 10); /* Name contents */ @@ -285,14 +288,14 @@ DEFINE_TEST(test_format_newc) "t2=%#08jx", (intmax_t)t, (intmax_t)t2); assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */ assertEqualMem(e + 54, "00000000", 8); /* File size */ - fs = from_hex(e + 54, 8); + fs = (uint64_t)from_hex(e + 54, 8); fs += PAD(fs, 4); assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */ assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */ assert(is_hex(e + 78, 8)); /* rdevmajor */ assert(is_hex(e + 86, 8)); /* rdevminor */ assertEqualMem(e + 94, "00000004", 8); /* Name size */ - ns = from_hex(e + 94, 8); + ns = (uint64_t)from_hex(e + 94, 8); ns += PAD(ns + 2, 4); assertEqualInt(0, from_hex(e + 102, 8)); /* check field */ assertEqualMem(e + 110, "dir\0\0\0", 6); /* Name contents */ @@ -319,14 +322,14 @@ DEFINE_TEST(test_format_newc) "t2=%#08jx", (intmax_t)t, (intmax_t)t2); assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */ assertEqualInt(10, from_hex(e + 54, 8)); /* File size */ - fs = from_hex(e + 54, 8); + fs = (uint64_t)from_hex(e + 54, 8); fs += PAD(fs, 4); assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */ assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */ assert(is_hex(e + 78, 8)); /* rdevmajor */ assert(is_hex(e + 86, 8)); /* rdevminor */ assertEqualMem(e + 94, "00000009", 8); /* Name size */ - ns = from_hex(e + 94, 8); + ns = (uint64_t)from_hex(e + 94, 8); ns += PAD(ns + 2, 4); assertEqualInt(0, from_hex(e + 102, 8)); /* check field */ assertEqualMem(e + 110, "hardlink\0\0", 10); /* Name contents */ diff --git a/contrib/libarchive/libarchive/archive_read.c b/contrib/libarchive/libarchive/archive_read.c index 31802ce8c7b5..c32526762708 100644 --- a/contrib/libarchive/libarchive/archive_read.c +++ b/contrib/libarchive/libarchive/archive_read.c @@ -892,15 +892,16 @@ archive_read_data(struct archive *_a, void *buff, size_t s) len = a->read_data_remaining; if (len > s) len = s; - if (len) + if (len) { memcpy(dest, a->read_data_block, len); - s -= len; - a->read_data_block += len; - a->read_data_remaining -= len; - a->read_data_output_offset += len; - a->read_data_offset += len; - dest += len; - bytes_read += len; + s -= len; + a->read_data_block += len; + a->read_data_remaining -= len; + a->read_data_output_offset += len; + a->read_data_offset += len; + dest += len; + bytes_read += len; + } } } a->read_data_is_posix_read = 0; diff --git a/contrib/libarchive/libarchive/archive_read_open_filename.c b/contrib/libarchive/libarchive/archive_read_open_filename.c index 64b017976209..f5bf8934eea2 100644 --- a/contrib/libarchive/libarchive/archive_read_open_filename.c +++ b/contrib/libarchive/libarchive/archive_read_open_filename.c @@ -221,7 +221,9 @@ file_open(struct archive *a, void *client_data) struct read_file_data *mine = (struct read_file_data *)client_data; void *buffer; const char *filename = NULL; +#if defined(_WIN32) && !defined(__CYGWIN__) const wchar_t *wfilename = NULL; +#endif int fd = -1; int is_disk_like = 0; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) @@ -281,10 +283,12 @@ file_open(struct archive *a, void *client_data) #endif } if (fstat(fd, &st) != 0) { +#if defined(_WIN32) && !defined(__CYGWIN__) if (mine->filename_type == FNT_WCS) archive_set_error(a, errno, "Can't stat '%S'", wfilename); else +#endif archive_set_error(a, errno, "Can't stat '%s'", filename); goto fail; diff --git a/contrib/libarchive/libarchive/archive_read_support_format_xar.c b/contrib/libarchive/libarchive/archive_read_support_format_xar.c index 7f8be398c7a2..503ff58b91db 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_xar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_xar.c @@ -458,6 +458,11 @@ archive_read_support_format_xar(struct archive *_a) return (ARCHIVE_FATAL); } + /* initialize xar->file_queue */ + xar->file_queue.allocated = 0; + xar->file_queue.used = 0; + xar->file_queue.files = NULL; + r = __archive_read_register_format(a, xar, "xar", @@ -1221,10 +1226,12 @@ heap_add_entry(struct archive_read *a, /* Expand our pending files list as necessary. */ if (heap->used >= heap->allocated) { struct xar_file **new_pending_files; - int new_size = heap->allocated * 2; + int new_size; if (heap->allocated < 1024) new_size = 1024; + else + new_size = heap->allocated * 2; /* Overflow might keep us from growing the list. */ if (new_size <= heap->allocated) { archive_set_error(&a->archive, @@ -1238,9 +1245,11 @@ heap_add_entry(struct archive_read *a, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); } - memcpy(new_pending_files, heap->files, - heap->allocated * sizeof(new_pending_files[0])); - free(heap->files); + if (heap->allocated) { + memcpy(new_pending_files, heap->files, + heap->allocated * sizeof(new_pending_files[0])); + free(heap->files); + } heap->files = new_pending_files; heap->allocated = new_size; } diff --git a/contrib/libarchive/libarchive/archive_util.c b/contrib/libarchive/libarchive/archive_util.c index eb75662379c4..037e63427ebe 100644 --- a/contrib/libarchive/libarchive/archive_util.c +++ b/contrib/libarchive/libarchive/archive_util.c @@ -365,6 +365,7 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) } fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR); if (fd == -1) { + la_dosmaperr(GetLastError()); CloseHandle(h); goto exit_tmpfile; } else diff --git a/contrib/libarchive/libarchive/archive_write_disk_posix.c b/contrib/libarchive/libarchive/archive_write_disk_posix.c index 34fde1671a18..9b0024dc7b0f 100644 --- a/contrib/libarchive/libarchive/archive_write_disk_posix.c +++ b/contrib/libarchive/libarchive/archive_write_disk_posix.c @@ -1856,8 +1856,9 @@ _archive_write_disk_finish_entry(struct archive *_a) if (a->tmpname) { if (rename(a->tmpname, a->name) == -1) { archive_set_error(&a->archive, errno, - "rename failed"); - ret = ARCHIVE_FATAL; + "Failed to rename temporary file"); + ret = ARCHIVE_FAILED; + unlink(a->tmpname); } a->tmpname = NULL; } @@ -2144,8 +2145,11 @@ restore_entry(struct archive_write_disk *a) if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) && S_ISREG(a->st.st_mode)) { /* Use a temporary file to extract */ - if ((a->fd = la_mktemp(a)) == -1) + if ((a->fd = la_mktemp(a)) == -1) { + archive_set_error(&a->archive, errno, + "Can't create temporary file"); return ARCHIVE_FAILED; + } a->pst = NULL; en = 0; } else { diff --git a/contrib/libarchive/libarchive/archive_write_set_format_xar.c b/contrib/libarchive/libarchive/archive_write_set_format_xar.c index d456cf8f8aa9..e1c7f3a96d4a 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_xar.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_xar.c @@ -681,7 +681,8 @@ xar_write_data(struct archive_write *a, const void *buff, size_t s) { struct xar *xar; enum la_zaction run; - size_t size, rsize; + size_t size = 0; + size_t rsize; int r; xar = (struct xar *)a->format_data; diff --git a/contrib/libarchive/libarchive/cpio.5 b/contrib/libarchive/libarchive/cpio.5 index 1a2886f08673..a91f0c596d2e 100644 --- a/contrib/libarchive/libarchive/cpio.5 +++ b/contrib/libarchive/libarchive/cpio.5 @@ -244,7 +244,7 @@ Note that this format supports only 4 gigabyte files (unlike the older ASCII format, which supports 8 gigabyte files). .Pp In this format, hardlinked files are handled by setting the -filesize to zero for each entry except the last one that +filesize to zero for each entry except the first one that appears in the archive. .Ss New CRC Format The CRC format is identical to the new ASCII format described diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip.c b/contrib/libarchive/libarchive/test/test_read_format_zip.c index 66d16018b1d1..ab99b0a8d92d 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip.c @@ -916,3 +916,53 @@ DEFINE_TEST(test_read_format_zip_lzma_alone_leak) * suite under Valgrind or ASan, the test runner won't return with * exit code 0 in case if a memory leak. */ } + +DEFINE_TEST(test_read_format_zip_lzma_stream_end) +{ + const char *refname = "test_read_format_zip_lzma_stream_end.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (lzma)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_zip_lzma_stream_end_blockread) +{ + const char *refname = "test_read_format_zip_lzma_stream_end.zipx"; + struct archive *a; + struct archive_entry *ae; + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + extract_reference_file(refname); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ZIP 6.3 (lzma)", archive_format_name(a)); + assertEqualString("vimrc", archive_entry_pathname(ae)); + assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_lzma_stream_end.zipx.uu b/contrib/libarchive/libarchive/test/test_read_format_zip_lzma_stream_end.zipx.uu new file mode 100644 index 000000000000..2b79bc221e0e --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_lzma_stream_end.zipx.uu @@ -0,0 +1,19 @@ +begin 664 test_read_format_zip_lzma_stream_end.zipx +M4$L#!#\``@`.`#TQD4VJ.XZZ/@(``)`#```%````=FEM)82Q1PWAL +M+U`,N0L_$]^&650C/X$D6#4QFD$\A/"_![4!O/5O/!KH`WCQ*4?T2*]4P#/D +M0'9I?EZG=N69Z0V;H0I=CP*$?".I\ +MGMG/80.A'^W>R4J'S/CZ%P`8`>F=R>R&R$2T@EM#X)"OQH1?A7,`:4IU9WV! +M#2W*DXT',;.4YIN4A:-X)O=IREL201ZSOC=YSAU[C4-::/YV8\)%"L17+>VC +M%/'B]ZCQN$2(Q*9*\KJZ`Y131`]5C&G';@1S-QES_RZF!2OX45@58+??ES%( +MUJ<(\`11M$NO)HK#/MK-9RT"15.2I:IZN8VTM1_?$G\L#BH67]$S%[4 +M%C-$\Q<+./&HV](4,7)OL-@C^M0F"2O!0N$OHOW54H87^QLBQVH*D%A<#SI% +M/#+-5U(W';:KC)RE>0Y^5YI!RECQNR"R4.UW9IR!@:B!UB8?_D5$FT8YCJHJ +M2[2"-&-_D2BJ6#XK[6G=%K"%;'^-+0]FHCY4ER#`^