MFV r358511,r358532:

Sync libarchive with vendor.

Relevant vendor changes:
  Issue #1257: Add testcase for ZIPX files with LZMA_STREAM_END marker
  PR #1331: cpio.5: fix hard link description
  Issue #1335: archive_read.c: fix UBSan warning about undefined behavior
  Issue #1338: XAR reader: fix UBSan warning about undefined behavior
  Issue #1339: bsdcpio_test: fix datatype in from_hex()
  Issue #1341: Safe writes: delete temporary file if rename fails.
  Issue #1341: Safe writes: improve error handling

MFC after:	1 week
This commit is contained in:
Martin Matuska 2020-03-02 08:44:58 +00:00
commit f55be4fc57
13 changed files with 133 additions and 40 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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));
}

View File

@ -0,0 +1,19 @@
begin 664 test_read_format_zip_lzma_stream_end.zipx
M4$L#!#\``@`.`#TQD4VJ.XZZ/@(``)`#```%````=FEM<F,)!`4`70``@```
M$0@$J,)\D;(#4L%<^$P5TO^CM0KI0HWG08B&_].4<,CJ")TW/L>)82Q1PWAL
M+U`,N0L_$]^&650C/X$D6#4QFD$\A/"_![4!O/5O/!KH`WCQ*4?T2*]4P#/D
M0'9I?EZG=N69Z0V;H0I=C<!C<J6O^834W097PY1$%=-++.YUA'!>P*$?".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:IZN8<TJR>VTM1_?$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#`^<I-M<!"D:-0H@);U"P"
MPYX+4#8!&$7\M.+%%MZ:KQ2GX0<]$"P7F^HT)J5JM<$VO9/D[#7KZ\'FITL/
MYIF"=GO+-L?F[8QS4KC7+=A)1`")V<.8DX629Q;;Y4XA\M-%O&MWC)^)`NO<
M.J6(5V2UY9"I(C*QKA[Z-GJ<5/_O%<=P4$L!`C\#/P`"``X`/3&13:H[CKH^
M`@``D`,```4``````````````+2!`````'9I;7)C4$L%!@`````!``$`,P``
'`&$"````````
`
end

View File

@ -598,6 +598,7 @@ ${PACKAGE}FILES+= test_read_format_zip_length_at_end.zip.uu
${PACKAGE}FILES+= test_read_format_zip_lzma_alone_leak.zipx.uu
${PACKAGE}FILES+= test_read_format_zip_lzma.zipx.uu
${PACKAGE}FILES+= test_read_format_zip_lzma_multi.zipx.uu
${PACKAGE}FILES+= test_read_format_zip_lzma_stream_end.zipx.uu
${PACKAGE}FILES+= test_read_format_zip_mac_metadata.zip.uu
${PACKAGE}FILES+= test_read_format_zip_malformed1.zip.uu
${PACKAGE}FILES+= test_read_format_zip_msdos.zip.uu