mirror of
https://git.freebsd.org/src.git
synced 2026-01-11 19:57:22 +00:00
libarchive: merge from vendor branch
libarchive 3.8.3 Important bugfixes: #2753 lib: Create temporary files in the target directory #2768 lha: Fix for an out-of-bounds buffer overrun when using p[H_LEVEL_OFFSET] #2769 7-zip: Fix a buffer overrun when reading truncated 7zip headers #2771 lz4 and zstd: Support both lz4 and zstd data with leading skippable frames Obtained from: libarchive Vendor commit: 1368b08875351df8aa268237b882c8f4ceb0882d MFC after: 1 week
This commit is contained in:
commit
007679a138
26 changed files with 7110 additions and 61 deletions
|
|
@ -1,3 +1,5 @@
|
|||
Nov 17, 2026: libarchive 3.8.3 released
|
||||
|
||||
Oct 15, 2026: libarchive 3.8.2 released
|
||||
|
||||
Jun 01, 2026: libarchive 3.8.1 released
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||
*/
|
||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3008002
|
||||
#define ARCHIVE_VERSION_NUMBER 3008003
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
|
|
@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void);
|
|||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.8.2"
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.8.3"
|
||||
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/* Note: Compiler will complain if this does not match archive.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3008002
|
||||
#define ARCHIVE_VERSION_NUMBER 3008003
|
||||
|
||||
/*
|
||||
* Note: archive_entry.h is for use outside of libarchive; the
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ for setting is recommended.
|
|||
The function
|
||||
.Fn archive_entry_size
|
||||
returns the file size, if it has been set, and 0 otherwise.
|
||||
.Fn archive_entry_size
|
||||
.Fn archive_entry_size_is_set
|
||||
can be used to query that status.
|
||||
.Fn archive_entry_set_size
|
||||
and
|
||||
|
|
|
|||
|
|
@ -358,12 +358,10 @@ setup_mac_metadata(struct archive_read_disk *a,
|
|||
return (ARCHIVE_OK);
|
||||
|
||||
archive_string_init(&tempfile);
|
||||
if (__archive_get_tempdir(&tempfile) != ARCHIVE_OK) {
|
||||
ret = ARCHIVE_WARN;
|
||||
goto cleanup;
|
||||
}
|
||||
archive_strcat(&tempfile, "tar.md.XXXXXX");
|
||||
tempfd = mkstemp(tempfile.s);
|
||||
archive_strcpy(&tempfile, name);
|
||||
archive_string_dirname(&tempfile);
|
||||
archive_strcat(&tempfile, "/tar.XXXXXXXX");
|
||||
tempfd = __archive_mkstemp(tempfile.s);
|
||||
if (tempfd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Could not open extended attribute file");
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@
|
|||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
#define MAX_FILESYSTEM_ID 1000000
|
||||
|
||||
#if defined(__hpux) && !defined(HAVE_DIRFD)
|
||||
#define dirfd(x) ((x)->__dd_fd)
|
||||
#define HAVE_DIRFD
|
||||
|
|
@ -1412,8 +1414,12 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
|
|||
* This is the new filesystem which we have to generate a new ID for.
|
||||
*/
|
||||
fid = t->max_filesystem_id++;
|
||||
if (fid > MAX_FILESYSTEM_ID) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Too many filesystems");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (t->max_filesystem_id > t->allocated_filesystem) {
|
||||
size_t s;
|
||||
int s;
|
||||
void *p;
|
||||
|
||||
s = t->max_filesystem_id * 2;
|
||||
|
|
@ -1693,8 +1699,6 @@ setup_current_filesystem(struct archive_read_disk *a)
|
|||
#endif
|
||||
t->current_filesystem->noatime = 0;
|
||||
|
||||
/* Set maximum filename length. */
|
||||
t->current_filesystem->name_max = svfs.f_namemax;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,9 +49,12 @@
|
|||
#include "archive_xxhash.h"
|
||||
|
||||
#define LZ4_MAGICNUMBER 0x184d2204
|
||||
#define LZ4_SKIPPABLED 0x184d2a50
|
||||
#define LZ4_LEGACY 0x184c2102
|
||||
|
||||
// Note: LZ4 and zstd share the same skippable frame format with the same magic numbers.
|
||||
#define LZ4_SKIPPABLE_START 0x184D2A50
|
||||
#define LZ4_SKIPPABLE_MASK 0xFFFFFFF0
|
||||
|
||||
#if defined(HAVE_LIBLZ4)
|
||||
struct private_data {
|
||||
enum { SELECT_STREAM,
|
||||
|
|
@ -141,19 +144,67 @@ lz4_reader_bid(struct archive_read_filter_bidder *self,
|
|||
{
|
||||
const unsigned char *buffer;
|
||||
ssize_t avail;
|
||||
int bits_checked;
|
||||
uint32_t number;
|
||||
int bits_checked = 0;
|
||||
ssize_t min_lz4_archive_size = 11;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
// LZ4 skippable frames contain a 4 byte magic number followed by
|
||||
// a 4 byte frame data size, then that number of bytes of data. Regular
|
||||
// frames contain a 4 byte magic number followed by a 2-14 byte frame
|
||||
// header, some data, and a 3 byte end marker.
|
||||
ssize_t min_lz4_frame_size = 8;
|
||||
|
||||
/* Minimal lz4 archive is 11 bytes. */
|
||||
buffer = __archive_read_filter_ahead(filter, 11, &avail);
|
||||
ssize_t offset_in_buffer = 0;
|
||||
ssize_t max_lookahead = 64 * 1024;
|
||||
|
||||
(void)self; // UNUSED
|
||||
|
||||
// Zstd and LZ4 skippable frame magic numbers are identical. To
|
||||
// differentiate these two, we need to look for a non-skippable
|
||||
// frame.
|
||||
|
||||
// Minimal lz4 archive is 11 bytes.
|
||||
buffer = __archive_read_filter_ahead(filter, min_lz4_archive_size, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
|
||||
/* First four bytes must be LZ4 magic numbers. */
|
||||
bits_checked = 0;
|
||||
if ((number = archive_le32dec(buffer)) == LZ4_MAGICNUMBER) {
|
||||
uint32_t magic_number = archive_le32dec(buffer);
|
||||
|
||||
while ((magic_number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) {
|
||||
|
||||
offset_in_buffer += 4; // Skip over the magic number
|
||||
|
||||
// Ensure that we can read another 4 bytes.
|
||||
if (offset_in_buffer + 4 > avail) {
|
||||
buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
}
|
||||
|
||||
uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer);
|
||||
|
||||
// Skip over the 4 frame data size bytes, plus the value stored there.
|
||||
offset_in_buffer += 4 + frame_data_size;
|
||||
|
||||
// There should be at least one more frame if this is LZ4 data.
|
||||
if (offset_in_buffer + min_lz4_frame_size > avail) { // TODO: should this be >= ?
|
||||
if (offset_in_buffer + min_lz4_frame_size > max_lookahead)
|
||||
return (0);
|
||||
|
||||
buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_lz4_frame_size, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
}
|
||||
|
||||
magic_number = archive_le32dec(buffer + offset_in_buffer);
|
||||
}
|
||||
|
||||
// We have skipped over any skippable frames. Either a regular LZ4 frame
|
||||
// follows, or this isn't LZ4 data.
|
||||
|
||||
bits_checked = offset_in_buffer;
|
||||
buffer = buffer + offset_in_buffer;
|
||||
|
||||
if (magic_number == LZ4_MAGICNUMBER) {
|
||||
unsigned char flag, BD;
|
||||
|
||||
bits_checked += 32;
|
||||
|
|
@ -175,11 +226,16 @@ lz4_reader_bid(struct archive_read_filter_bidder *self,
|
|||
if (BD & ~0x70)
|
||||
return (0);
|
||||
bits_checked += 8;
|
||||
} else if (number == LZ4_LEGACY) {
|
||||
bits_checked += 32;
|
||||
|
||||
return (bits_checked);
|
||||
}
|
||||
|
||||
return (bits_checked);
|
||||
|
||||
if (magic_number == LZ4_LEGACY) {
|
||||
bits_checked += 32;
|
||||
return (bits_checked);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if !defined(HAVE_LIBLZ4)
|
||||
|
|
@ -342,7 +398,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p)
|
|||
return lz4_filter_read_default_stream(self, p);
|
||||
else if (number == LZ4_LEGACY)
|
||||
return lz4_filter_read_legacy_stream(self, p);
|
||||
else if ((number & ~0xF) == LZ4_SKIPPABLED) {
|
||||
else if ((number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) {
|
||||
read_buf = __archive_read_filter_ahead(
|
||||
self->upstream, 4, NULL);
|
||||
if (read_buf == NULL) {
|
||||
|
|
|
|||
|
|
@ -110,24 +110,67 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self,
|
|||
{
|
||||
const unsigned char *buffer;
|
||||
ssize_t avail;
|
||||
unsigned prefix;
|
||||
|
||||
/* Zstd frame magic values */
|
||||
unsigned zstd_magic = 0xFD2FB528U;
|
||||
unsigned zstd_magic_skippable_start = 0x184D2A50U;
|
||||
unsigned zstd_magic_skippable_mask = 0xFFFFFFF0;
|
||||
// Zstandard skippable frames contain a 4 byte magic number followed by
|
||||
// a 4 byte frame data size, then that number of bytes of data. Regular
|
||||
// frames contain a 4 byte magic number followed by a 2-14 byte frame
|
||||
// header, some data, and a 3 byte end marker.
|
||||
ssize_t min_zstd_frame_size = 8;
|
||||
|
||||
(void) self; /* UNUSED */
|
||||
ssize_t offset_in_buffer = 0;
|
||||
ssize_t max_lookahead = 64 * 1024;
|
||||
|
||||
buffer = __archive_read_filter_ahead(filter, 4, &avail);
|
||||
// Zstd regular frame magic number.
|
||||
uint32_t zstd_magic = 0xFD2FB528U;
|
||||
|
||||
// Note: Zstd and LZ4 skippable frame magic numbers are identical.
|
||||
// To differentiate these two, we need to look for a non-skippable
|
||||
// frame.
|
||||
uint32_t zstd_magic_skippable_start = 0x184D2A50;
|
||||
uint32_t zstd_magic_skippable_mask = 0xFFFFFFF0;
|
||||
|
||||
(void) self; // UNUSED
|
||||
|
||||
buffer = __archive_read_filter_ahead(filter, min_zstd_frame_size, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
|
||||
prefix = archive_le32dec(buffer);
|
||||
if (prefix == zstd_magic)
|
||||
return (32);
|
||||
if ((prefix & zstd_magic_skippable_mask) == zstd_magic_skippable_start)
|
||||
return (32);
|
||||
uint32_t magic_number = archive_le32dec(buffer);
|
||||
|
||||
while ((magic_number & zstd_magic_skippable_mask) == zstd_magic_skippable_start) {
|
||||
|
||||
offset_in_buffer += 4; // Skip over the magic number
|
||||
|
||||
// Ensure that we can read another 4 bytes.
|
||||
if (offset_in_buffer + 4 > avail) {
|
||||
buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
}
|
||||
|
||||
uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer);
|
||||
|
||||
// Skip over the 4 frame data size bytes, plus the value stored there.
|
||||
offset_in_buffer += 4 + frame_data_size;
|
||||
|
||||
// There should be at least one more frame if this is zstd data.
|
||||
if (offset_in_buffer + min_zstd_frame_size > avail) {
|
||||
if (offset_in_buffer + min_zstd_frame_size > max_lookahead)
|
||||
return (0);
|
||||
|
||||
buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_zstd_frame_size, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
}
|
||||
|
||||
magic_number = archive_le32dec(buffer + offset_in_buffer);
|
||||
}
|
||||
|
||||
// We have skipped over any skippable frames. Either a regular zstd frame
|
||||
// follows, or this isn't zstd data.
|
||||
|
||||
if (magic_number == zstd_magic)
|
||||
return (offset_in_buffer + 4);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -744,6 +744,7 @@ find_elf_data_sec(struct archive_read *a)
|
|||
const char *h;
|
||||
char big_endian, format_64;
|
||||
ssize_t bytes, min_addr = SFX_MIN_ADDR;
|
||||
ssize_t request;
|
||||
uint64_t e_shoff, strtab_offset, strtab_size;
|
||||
uint16_t e_shentsize, e_shnum, e_shstrndx;
|
||||
uint16_t (*dec16)(const void *);
|
||||
|
|
@ -796,7 +797,12 @@ find_elf_data_sec(struct archive_read *a)
|
|||
if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) {
|
||||
break;
|
||||
}
|
||||
h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL);
|
||||
if (format_64) {
|
||||
request = (size_t)e_shnum * (size_t)e_shentsize + 0x28;
|
||||
} else {
|
||||
request = (size_t)e_shnum * (size_t)e_shentsize + 0x18;
|
||||
}
|
||||
h = __archive_read_ahead(a, request, &bytes);
|
||||
if (h == NULL) {
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -689,7 +689,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
|
|||
* a pathname and a symlink has '\' character, a directory
|
||||
* separator in DOS/Windows. So we should convert it to '/'.
|
||||
*/
|
||||
if (p[H_LEVEL_OFFSET] == 0)
|
||||
if (lha->level == 0)
|
||||
lha_replace_path_separator(lha, entry);
|
||||
|
||||
archive_entry_set_mode(entry, lha->mode);
|
||||
|
|
|
|||
|
|
@ -2311,6 +2311,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *
|
|||
archive_string_init(&as);
|
||||
r = read_bytes_to_string(a, &as, value_length, &unconsumed);
|
||||
if (tar_flush_unconsumed(a, &unconsumed) != ARCHIVE_OK) {
|
||||
*result = 0;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (r < ARCHIVE_OK) {
|
||||
|
|
|
|||
|
|
@ -78,6 +78,12 @@
|
|||
#include "archive_crc32.h"
|
||||
#endif
|
||||
|
||||
/* length of local file header, not including filename and extra */
|
||||
#define ZIP_LOCHDR_LEN 30U
|
||||
|
||||
/* maximum length of Mac metadata in MiB */
|
||||
#define ZIP_MAX_METADATA 10U
|
||||
|
||||
struct zip_entry {
|
||||
struct archive_rb_node node;
|
||||
struct zip_entry *next;
|
||||
|
|
@ -933,7 +939,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
|||
zip->init_default_conversion = 1;
|
||||
}
|
||||
|
||||
if ((p = __archive_read_ahead(a, 30, NULL)) == NULL) {
|
||||
if ((p = __archive_read_ahead(a, ZIP_LOCHDR_LEN, NULL)) == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file header");
|
||||
return (ARCHIVE_FATAL);
|
||||
|
|
@ -969,7 +975,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
|||
filename_length = archive_le16dec(p + 26);
|
||||
extra_length = archive_le16dec(p + 28);
|
||||
|
||||
__archive_read_consume(a, 30);
|
||||
__archive_read_consume(a, ZIP_LOCHDR_LEN);
|
||||
|
||||
/* Read the filename. */
|
||||
if ((h = __archive_read_ahead(a, filename_length, NULL)) == NULL) {
|
||||
|
|
@ -3637,7 +3643,7 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset)
|
|||
{
|
||||
uint16_t disk_num;
|
||||
uint32_t cd_size, cd_offset;
|
||||
|
||||
|
||||
disk_num = archive_le16dec(p + 4);
|
||||
cd_size = archive_le32dec(p + 12);
|
||||
cd_offset = archive_le32dec(p + 16);
|
||||
|
|
@ -4097,7 +4103,7 @@ zip_get_local_file_header_size(struct archive_read *a, size_t extra)
|
|||
const char *p;
|
||||
ssize_t filename_length, extra_length;
|
||||
|
||||
if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) {
|
||||
if ((p = __archive_read_ahead(a, extra + ZIP_LOCHDR_LEN, NULL)) == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file header");
|
||||
return (ARCHIVE_WARN);
|
||||
|
|
@ -4111,7 +4117,7 @@ zip_get_local_file_header_size(struct archive_read *a, size_t extra)
|
|||
filename_length = archive_le16dec(p + 26);
|
||||
extra_length = archive_le16dec(p + 28);
|
||||
|
||||
return (30 + filename_length + extra_length);
|
||||
return (ZIP_LOCHDR_LEN + filename_length + extra_length);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -4148,16 +4154,16 @@ zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
|
|||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
if (rsrc->uncompressed_size > (4 * 1024 * 1024)) {
|
||||
if (rsrc->uncompressed_size > ZIP_MAX_METADATA * 1048576U) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Mac metadata is too large: %jd > 4M bytes",
|
||||
(intmax_t)rsrc->uncompressed_size);
|
||||
"Mac metadata is too large: %jd > %u MiB",
|
||||
(intmax_t)rsrc->uncompressed_size, ZIP_MAX_METADATA);
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
if (rsrc->compressed_size > (4 * 1024 * 1024)) {
|
||||
if (rsrc->compressed_size > ZIP_MAX_METADATA * 1048576U) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Mac metadata is too large: %jd > 4M bytes",
|
||||
(intmax_t)rsrc->compressed_size);
|
||||
"Mac metadata is too large: %jd > %u MiB",
|
||||
(intmax_t)rsrc->compressed_size, ZIP_MAX_METADATA);
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2054,6 +2054,26 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
|
|||
return (r);
|
||||
}
|
||||
|
||||
struct archive_string *
|
||||
archive_string_dirname(struct archive_string *as)
|
||||
{
|
||||
/* strip trailing separators */
|
||||
while (as->length > 1 && as->s[as->length - 1] == '/')
|
||||
as->length--;
|
||||
/* strip final component */
|
||||
while (as->length > 0 && as->s[as->length - 1] != '/')
|
||||
as->length--;
|
||||
/* empty path -> cwd */
|
||||
if (as->length == 0)
|
||||
return (archive_strcat(as, "."));
|
||||
/* strip separator(s) */
|
||||
while (as->length > 1 && as->s[as->length - 1] == '/')
|
||||
as->length--;
|
||||
/* terminate */
|
||||
as->s[as->length] = '\0';
|
||||
return (as);
|
||||
}
|
||||
|
||||
#if HAVE_ICONV
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -192,6 +192,10 @@ void archive_string_vsprintf(struct archive_string *, const char *,
|
|||
void archive_string_sprintf(struct archive_string *, const char *, ...)
|
||||
__LA_PRINTF(2, 3);
|
||||
|
||||
/* Equivalent to dirname(3) */
|
||||
struct archive_string *
|
||||
archive_string_dirname(struct archive_string *);
|
||||
|
||||
/* Translates from MBS to Unicode. */
|
||||
/* Returns non-zero if conversion failed in any way. */
|
||||
int archive_wstring_append_from_mbs(struct archive_wstring *dest,
|
||||
|
|
|
|||
|
|
@ -412,12 +412,14 @@ static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
|
|||
static int
|
||||
la_mktemp(struct archive_write_disk *a)
|
||||
{
|
||||
struct archive_string *tmp = &a->_tmpname_data;
|
||||
int oerrno, fd;
|
||||
mode_t mode;
|
||||
|
||||
archive_string_empty(&a->_tmpname_data);
|
||||
archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name);
|
||||
a->tmpname = a->_tmpname_data.s;
|
||||
archive_strcpy(tmp, a->name);
|
||||
archive_string_dirname(tmp);
|
||||
archive_strcat(tmp, "/tar.XXXXXXXX");
|
||||
a->tmpname = tmp->s;
|
||||
|
||||
fd = __archive_mkstemp(a->tmpname);
|
||||
if (fd == -1)
|
||||
|
|
@ -4287,8 +4289,10 @@ create_tempdatafork(struct archive_write_disk *a, const char *pathname)
|
|||
int tmpfd;
|
||||
|
||||
archive_string_init(&tmpdatafork);
|
||||
archive_strcpy(&tmpdatafork, "tar.md.XXXXXX");
|
||||
tmpfd = mkstemp(tmpdatafork.s);
|
||||
archive_strcpy(&tmpdatafork, pathname);
|
||||
archive_string_dirname(&tmpdatafork);
|
||||
archive_strcat(&tmpdatafork, "/tar.XXXXXXXX");
|
||||
tmpfd = __archive_mkstemp(tmpdatafork.s);
|
||||
if (tmpfd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to mkstemp");
|
||||
|
|
@ -4367,8 +4371,10 @@ set_mac_metadata(struct archive_write_disk *a, const char *pathname,
|
|||
* silly dance of writing the data to disk just so that
|
||||
* copyfile() can read it back in again. */
|
||||
archive_string_init(&tmp);
|
||||
archive_strcpy(&tmp, "tar.mmd.XXXXXX");
|
||||
fd = mkstemp(tmp.s);
|
||||
archive_strcpy(&tmp, pathname);
|
||||
archive_string_dirname(&tmp);
|
||||
archive_strcat(&tmp, "/tar.XXXXXXXX");
|
||||
fd = __archive_mkstemp(tmp.s);
|
||||
|
||||
if (fd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
|
|
|
|||
|
|
@ -191,6 +191,8 @@ file_open(struct archive *a, void *client_data)
|
|||
archive_set_error(a, errno, "Couldn't stat '%s'", mbs);
|
||||
else
|
||||
archive_set_error(a, errno, "Couldn't stat '%ls'", wcs);
|
||||
close(mine->fd);
|
||||
mine->fd = -1;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
|
|
|
|||
34
contrib/libarchive/libarchive/module.modulemap
Normal file
34
contrib/libarchive/libarchive/module.modulemap
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Clang Module Map for libarchive
|
||||
*
|
||||
* What this is:
|
||||
* This file tells the Clang compiler how to treat libarchive as a "module" -
|
||||
* a self-contained unit of code that can be imported all at once instead of
|
||||
* including individual header files. Think of it like a package definition.
|
||||
*
|
||||
* How it works:
|
||||
* - When you write `@import CArchive` (Objective-C) or `import CArchive` (Swift),
|
||||
* the compiler uses this file to know which headers belong to libarchive
|
||||
* - Instead of processing each #include separately, the compiler can load a
|
||||
* pre-compiled version of the entire library, making builds faster
|
||||
* - This also provides better dependency tracking and can catch issues like
|
||||
* conflicting macro definitions between libraries
|
||||
*
|
||||
* When to update:
|
||||
* Update this file whenever:
|
||||
* - New public header files are added to libarchive's libarchive/ directory
|
||||
* - Public headers are removed or renamed
|
||||
* - The library's API structure changes significantly
|
||||
*
|
||||
* You typically don't need to update this for:
|
||||
* - Internal implementation changes
|
||||
* - Private/internal header modifications
|
||||
* - Documentation updates
|
||||
*
|
||||
* NOTE: This only affects projects using Clang with modules enabled. Traditional
|
||||
* #include-based builds will continue to work normally with or without this file.
|
||||
*/
|
||||
module CArchive {
|
||||
header "archive.h"
|
||||
header "archive_entry.h"
|
||||
}
|
||||
|
|
@ -353,6 +353,43 @@ test_archive_string_sprintf(void)
|
|||
archive_string_free(&s);
|
||||
}
|
||||
|
||||
static void
|
||||
test_archive_string_dirname(void)
|
||||
{
|
||||
static struct pair { const char *str, *exp; } pairs[] = {
|
||||
{ "", "." },
|
||||
{ "/", "/" },
|
||||
{ "//", "/" },
|
||||
{ "///", "/" },
|
||||
{ "./", "." },
|
||||
{ ".", "." },
|
||||
{ "..", "." },
|
||||
{ "foo", "." },
|
||||
{ "foo/", "." },
|
||||
{ "foo//", "." },
|
||||
{ "foo/bar", "foo" },
|
||||
{ "foo/bar/", "foo" },
|
||||
{ "foo/bar//", "foo" },
|
||||
{ "foo//bar", "foo" },
|
||||
{ "foo//bar/", "foo" },
|
||||
{ "foo//bar//", "foo" },
|
||||
{ "/foo", "/" },
|
||||
{ "//foo", "/" },
|
||||
{ "//foo/", "/" },
|
||||
{ "//foo//", "/" },
|
||||
{ 0 },
|
||||
};
|
||||
struct pair *pair;
|
||||
struct archive_string s;
|
||||
|
||||
archive_string_init(&s);
|
||||
for (pair = pairs; pair->str; pair++) {
|
||||
archive_strcpy(&s, pair->str);
|
||||
archive_string_dirname(&s);
|
||||
assertEqualString(pair->exp, s.s);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_archive_string)
|
||||
{
|
||||
test_archive_string_ensure();
|
||||
|
|
@ -364,6 +401,7 @@ DEFINE_TEST(test_archive_string)
|
|||
test_archive_string_concat();
|
||||
test_archive_string_copy();
|
||||
test_archive_string_sprintf();
|
||||
test_archive_string_dirname();
|
||||
}
|
||||
|
||||
static const char *strings[] =
|
||||
|
|
|
|||
|
|
@ -98,6 +98,8 @@ DEFINE_TEST(test_compat_lz4)
|
|||
verify("test_compat_lz4_3.tar.lz4.uu", n);
|
||||
/* This sample has been compressed with -B4 option. */
|
||||
verify("test_compat_lz4_B4.tar.lz4.uu", n2);
|
||||
/* This sample has been compresed with -B4, and has two skippable frames at the start. */
|
||||
verify("test_compat_lz4_skippable_frames_B4.tar.lz4.uu", n2);
|
||||
/* This sample has been compressed with -B5 option. */
|
||||
verify("test_compat_lz4_B5.tar.lz4.uu", n2);
|
||||
/* This sample has been compressed with -B6 option. */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,5 @@
|
|||
begin 644 test_read_format_7zip_issue2765.7z
|
||||
M?T5,1@$!`0!@```(0``````````R````-``@``$`````````````````````
|
||||
D1TD``0`!````4$L`</]_```````````(````N`$```#-@```
|
||||
`
|
||||
end
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*-
|
||||
* Copyright (c) 2025 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
|
||||
/*
|
||||
* Sample file from Github Issue #2765
|
||||
*/
|
||||
DEFINE_TEST(test_read_format_7zip_issue2765)
|
||||
{
|
||||
const char *refname = "test_read_format_7zip_issue2765.7z";
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
|
||||
extract_reference_file(refname);
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_FATAL,
|
||||
archive_read_open_filename(a, refname, 10240));
|
||||
|
||||
/* End of archive. */
|
||||
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
|
||||
|
||||
assertEqualInt(0, archive_file_count(a));
|
||||
|
||||
/* Close the archive. */
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
DEFINE_TEST(test_option_safe_writes)
|
||||
{
|
||||
assertUmask(0);
|
||||
/* Create files */
|
||||
assertMakeDir("in", 0755);
|
||||
assertEqualInt(0, chdir("in"));
|
||||
|
|
|
|||
|
|
@ -314,7 +314,10 @@ set_chdir(struct bsdtar *bsdtar, const char *newdir)
|
|||
/* The -C /foo -C bar case; concatenate */
|
||||
char *old_pending = bsdtar->pending_chdir;
|
||||
size_t old_len = strlen(old_pending);
|
||||
size_t new_len = old_len + strlen(newdir) + 2;
|
||||
size_t newdir_len = strlen(newdir);
|
||||
size_t new_len = old_len + newdir_len + 2;
|
||||
if (old_len > SIZE_MAX - newdir_len - 2)
|
||||
lafe_errc(1, errno, "Path too long");
|
||||
bsdtar->pending_chdir = malloc(new_len);
|
||||
if (old_pending[old_len - 1] == '/')
|
||||
old_pending[old_len - 1] = '\0';
|
||||
|
|
|
|||
|
|
@ -84,6 +84,18 @@
|
|||
#if HAVE_MEMBERSHIP_H
|
||||
#include <membership.h>
|
||||
#endif
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
# if HAVE_POSIX_SPAWN
|
||||
# if HAVE_SYS_WAIT_H
|
||||
# include <sys/wait.h>
|
||||
# endif
|
||||
# if HAVE_SPAWN_H
|
||||
# include <spawn.h>
|
||||
# endif
|
||||
extern char **environ;
|
||||
# define USE_POSIX_SPAWN 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef nitems
|
||||
#define nitems(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
|
@ -3009,15 +3021,28 @@ int
|
|||
systemf(const char *fmt, ...)
|
||||
{
|
||||
char buff[8192];
|
||||
#if USE_POSIX_SPAWN
|
||||
char *argv[] = { "/bin/sh", "-c", buff, NULL };
|
||||
pid_t pid;
|
||||
#endif
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buff, sizeof(buff), fmt, ap);
|
||||
va_end(ap);
|
||||
if (verbosity > VERBOSITY_FULL)
|
||||
logprintf("Cmd: %s\n", buff);
|
||||
#if USE_POSIX_SPAWN
|
||||
if ((r = posix_spawn(&pid, *argv, NULL, NULL, argv, environ)) == 0) {
|
||||
while (waitpid(pid, &r, 0) == -1) {
|
||||
if (errno != EINTR)
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
r = system(buff);
|
||||
va_end(ap);
|
||||
#endif
|
||||
return (r);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ TESTS_SRCS= \
|
|||
test_read_format_7zip_encryption_data.c \
|
||||
test_read_format_7zip_encryption_header.c \
|
||||
test_read_format_7zip_encryption_partially.c \
|
||||
test_read_format_7zip_issue2765.c \
|
||||
test_read_format_7zip_malformed.c \
|
||||
test_read_format_7zip_packinfo_digests.c \
|
||||
test_read_format_ar.c \
|
||||
|
|
@ -392,6 +393,7 @@ ${PACKAGE}FILES+= test_compat_lz4_B6.tar.lz4.uu
|
|||
${PACKAGE}FILES+= test_compat_lz4_B6BD.tar.lz4.uu
|
||||
${PACKAGE}FILES+= test_compat_lz4_B7.tar.lz4.uu
|
||||
${PACKAGE}FILES+= test_compat_lz4_B7BD.tar.lz4.uu
|
||||
${PACKAGE}FILES+= test_compat_lz4_skippable_frames_B4.tar.lz4.uu
|
||||
${PACKAGE}FILES+= test_compat_lzip_1.tlz.uu
|
||||
${PACKAGE}FILES+= test_compat_lzip_2.tlz.uu
|
||||
${PACKAGE}FILES+= test_compat_lzip_3.lz.uu
|
||||
|
|
@ -485,6 +487,7 @@ ${PACKAGE}FILES+= test_read_format_7zip_encryption.7z.uu
|
|||
${PACKAGE}FILES+= test_read_format_7zip_encryption_header.7z.uu
|
||||
${PACKAGE}FILES+= test_read_format_7zip_encryption_partially.7z.uu
|
||||
${PACKAGE}FILES+= test_read_format_7zip_extract_second.7z.uu
|
||||
${PACKAGE}FILES+= test_read_format_7zip_issue2765.7z.uu
|
||||
${PACKAGE}FILES+= test_read_format_7zip_lzma1.7z.uu
|
||||
${PACKAGE}FILES+= test_read_format_7zip_lzma1_2.7z.uu
|
||||
${PACKAGE}FILES+= test_read_format_7zip_lzma1_lzma2.7z.uu
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue