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:
commit
f55be4fc57
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user