Compare commits
6
Commits
mingw-fixes
...
patch/3.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
673c1eae89 | ||
|
|
e346721205 | ||
|
|
05591dd516 | ||
|
|
bcc48ee860 | ||
|
|
9516eda33d | ||
|
|
4f8ad2f107 |
No files matched your search
+1
-1
@@ -18,7 +18,7 @@ endif()
|
||||
# RelWithDebInfo : Release build with Debug Info
|
||||
# MinSizeRel : Release Min Size build
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
|
||||
SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
|
||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
||||
# Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the
|
||||
# value type is "UNINITIALIZED".
|
||||
|
||||
@@ -887,6 +887,9 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_rar5_arm_filter_on_window_boundary.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_decode_number_out_of_bounds_read.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_window_buf_and_size_desync.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_bad_window_sz_in_mltarc_file.rar.uu \
|
||||
libarchive/test/test_read_format_raw.bufr.uu \
|
||||
libarchive/test/test_read_format_raw.data.gz.uu \
|
||||
libarchive/test/test_read_format_raw.data.Z.uu \
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
Feb 08, 2022: libarchive 3.5.3 released
|
||||
|
||||
Aug 22, 2021: libarchive 3.5.2 released
|
||||
|
||||
Dec 26, 2020: libarchive 3.5.1 released
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3005003dev
|
||||
3005003
|
||||
+1
-1
@@ -4,7 +4,7 @@ dnl First, define all of the version numbers up front.
|
||||
dnl In particular, this allows the version macro to be used in AC_INIT
|
||||
|
||||
dnl These first two version numbers are updated automatically on each release.
|
||||
m4_define([LIBARCHIVE_VERSION_S],[3.5.3dev])
|
||||
m4_define([LIBARCHIVE_VERSION_S],[3.5.3])
|
||||
m4_define([LIBARCHIVE_VERSION_N],[3005003])
|
||||
|
||||
dnl bsdtar and bsdcpio versioning tracks libarchive
|
||||
|
||||
@@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
|
||||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.5.3dev"
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.5.3"
|
||||
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
|
||||
@@ -1012,7 +1012,16 @@ static int read_var_sized(struct archive_read* a, size_t* pvalue,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int read_bits_32(struct rar5* rar, const uint8_t* p, uint32_t* value) {
|
||||
static int read_bits_32(struct archive_read* a, struct rar5* rar,
|
||||
const uint8_t* p, uint32_t* value)
|
||||
{
|
||||
if(rar->bits.in_addr >= rar->cstate.cur_block_size) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Premature end of stream during extraction of data (#1)");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
uint32_t bits = ((uint32_t) p[rar->bits.in_addr]) << 24;
|
||||
bits |= p[rar->bits.in_addr + 1] << 16;
|
||||
bits |= p[rar->bits.in_addr + 2] << 8;
|
||||
@@ -1023,7 +1032,16 @@ static int read_bits_32(struct rar5* rar, const uint8_t* p, uint32_t* value) {
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
static int read_bits_16(struct rar5* rar, const uint8_t* p, uint16_t* value) {
|
||||
static int read_bits_16(struct archive_read* a, struct rar5* rar,
|
||||
const uint8_t* p, uint16_t* value)
|
||||
{
|
||||
if(rar->bits.in_addr >= rar->cstate.cur_block_size) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Premature end of stream during extraction of data (#2)");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
int bits = (int) ((uint32_t) p[rar->bits.in_addr]) << 16;
|
||||
bits |= (int) p[rar->bits.in_addr + 1] << 8;
|
||||
bits |= (int) p[rar->bits.in_addr + 2];
|
||||
@@ -1039,8 +1057,8 @@ static void skip_bits(struct rar5* rar, int bits) {
|
||||
}
|
||||
|
||||
/* n = up to 16 */
|
||||
static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n,
|
||||
int* value)
|
||||
static int read_consume_bits(struct archive_read* a, struct rar5* rar,
|
||||
const uint8_t* p, int n, int* value)
|
||||
{
|
||||
uint16_t v;
|
||||
int ret, num;
|
||||
@@ -1051,7 +1069,7 @@ static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n,
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
ret = read_bits_16(rar, p, &v);
|
||||
ret = read_bits_16(a, rar, p, &v);
|
||||
if(ret != ARCHIVE_OK)
|
||||
return ret;
|
||||
|
||||
@@ -1712,14 +1730,29 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're currently switching volumes, ignore the new definition of
|
||||
* window_size. */
|
||||
if(rar->cstate.switch_multivolume == 0) {
|
||||
/* Values up to 64M should fit into ssize_t on every
|
||||
* architecture. */
|
||||
rar->cstate.window_size = (ssize_t) window_size;
|
||||
if(rar->cstate.window_size < (ssize_t) window_size &&
|
||||
rar->cstate.window_buf)
|
||||
{
|
||||
/* If window_buf has been allocated before, reallocate it, so
|
||||
* that its size will match new window_size. */
|
||||
|
||||
uint8_t* new_window_buf =
|
||||
realloc(rar->cstate.window_buf, window_size);
|
||||
|
||||
if(!new_window_buf) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Not enough memory when trying to realloc the window "
|
||||
"buffer.");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
rar->cstate.window_buf = new_window_buf;
|
||||
}
|
||||
|
||||
/* Values up to 64M should fit into ssize_t on every
|
||||
* architecture. */
|
||||
rar->cstate.window_size = (ssize_t) window_size;
|
||||
|
||||
if(rar->file.solid > 0 && rar->file.solid_window_size == 0) {
|
||||
/* Solid files have to have the same window_size across
|
||||
whole archive. Remember the window_size parameter
|
||||
@@ -2425,13 +2458,13 @@ static int create_decode_tables(uint8_t* bit_length,
|
||||
static int decode_number(struct archive_read* a, struct decode_table* table,
|
||||
const uint8_t* p, uint16_t* num)
|
||||
{
|
||||
int i, bits, dist;
|
||||
int i, bits, dist, ret;
|
||||
uint16_t bitfield;
|
||||
uint32_t pos;
|
||||
struct rar5* rar = get_context(a);
|
||||
|
||||
if(ARCHIVE_OK != read_bits_16(rar, p, &bitfield)) {
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &bitfield))) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bitfield &= 0xfffe;
|
||||
@@ -2537,14 +2570,6 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
|
||||
for(i = 0; i < HUFF_TABLE_SIZE;) {
|
||||
uint16_t num;
|
||||
|
||||
if((rar->bits.in_addr + 6) >= rar->cstate.cur_block_size) {
|
||||
/* Truncated data, can't continue. */
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated data in huffman tables (#2)");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
ret = decode_number(a, &rar->cstate.bd, p, &num);
|
||||
if(ret != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive,
|
||||
@@ -2561,8 +2586,8 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
|
||||
/* 16..17: repeat previous code */
|
||||
uint16_t n;
|
||||
|
||||
if(ARCHIVE_OK != read_bits_16(rar, p, &n))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
|
||||
return ret;
|
||||
|
||||
if(num == 16) {
|
||||
n >>= 13;
|
||||
@@ -2590,8 +2615,8 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
|
||||
/* other codes: fill with zeroes `n` times */
|
||||
uint16_t n;
|
||||
|
||||
if(ARCHIVE_OK != read_bits_16(rar, p, &n))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
|
||||
return ret;
|
||||
|
||||
if(num == 18) {
|
||||
n >>= 13;
|
||||
@@ -2707,22 +2732,22 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p,
|
||||
}
|
||||
|
||||
/* Convenience function used during filter processing. */
|
||||
static int parse_filter_data(struct rar5* rar, const uint8_t* p,
|
||||
uint32_t* filter_data)
|
||||
static int parse_filter_data(struct archive_read* a, struct rar5* rar,
|
||||
const uint8_t* p, uint32_t* filter_data)
|
||||
{
|
||||
int i, bytes;
|
||||
int i, bytes, ret;
|
||||
uint32_t data = 0;
|
||||
|
||||
if(ARCHIVE_OK != read_consume_bits(rar, p, 2, &bytes))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_consume_bits(a, rar, p, 2, &bytes)))
|
||||
return ret;
|
||||
|
||||
bytes++;
|
||||
|
||||
for(i = 0; i < bytes; i++) {
|
||||
uint16_t byte;
|
||||
|
||||
if(ARCHIVE_OK != read_bits_16(rar, p, &byte)) {
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &byte))) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Cast to uint32_t will ensure the shift operation will not
|
||||
@@ -2765,16 +2790,17 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
|
||||
uint16_t filter_type;
|
||||
struct filter_info* filt = NULL;
|
||||
struct rar5* rar = get_context(ar);
|
||||
int ret;
|
||||
|
||||
/* Read the parameters from the input stream. */
|
||||
if(ARCHIVE_OK != parse_filter_data(rar, p, &block_start))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_start)))
|
||||
return ret;
|
||||
|
||||
if(ARCHIVE_OK != parse_filter_data(rar, p, &block_length))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_length)))
|
||||
return ret;
|
||||
|
||||
if(ARCHIVE_OK != read_bits_16(rar, p, &filter_type))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_bits_16(ar, rar, p, &filter_type)))
|
||||
return ret;
|
||||
|
||||
filter_type >>= 13;
|
||||
skip_bits(rar, 3);
|
||||
@@ -2814,8 +2840,8 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
|
||||
if(filter_type == FILTER_DELTA) {
|
||||
int channels;
|
||||
|
||||
if(ARCHIVE_OK != read_consume_bits(rar, p, 5, &channels))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_consume_bits(ar, rar, p, 5, &channels)))
|
||||
return ret;
|
||||
|
||||
filt->channels = channels + 1;
|
||||
}
|
||||
@@ -2823,10 +2849,11 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
static int decode_code_length(struct rar5* rar, const uint8_t* p,
|
||||
uint16_t code)
|
||||
static int decode_code_length(struct archive_read* a, struct rar5* rar,
|
||||
const uint8_t* p, uint16_t code)
|
||||
{
|
||||
int lbits, length = 2;
|
||||
|
||||
if(code < 8) {
|
||||
lbits = 0;
|
||||
length += code;
|
||||
@@ -2838,7 +2865,7 @@ static int decode_code_length(struct rar5* rar, const uint8_t* p,
|
||||
if(lbits > 0) {
|
||||
int add;
|
||||
|
||||
if(ARCHIVE_OK != read_consume_bits(rar, p, lbits, &add))
|
||||
if(ARCHIVE_OK != read_consume_bits(a, rar, p, lbits, &add))
|
||||
return -1;
|
||||
|
||||
length += add;
|
||||
@@ -2933,7 +2960,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
||||
continue;
|
||||
} else if(num >= 262) {
|
||||
uint16_t dist_slot;
|
||||
int len = decode_code_length(rar, p, num - 262),
|
||||
int len = decode_code_length(a, rar, p, num - 262),
|
||||
dbits,
|
||||
dist = 1;
|
||||
|
||||
@@ -2975,12 +3002,12 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
||||
uint16_t low_dist;
|
||||
|
||||
if(dbits > 4) {
|
||||
if(ARCHIVE_OK != read_bits_32(
|
||||
rar, p, &add)) {
|
||||
if(ARCHIVE_OK != (ret = read_bits_32(
|
||||
a, rar, p, &add))) {
|
||||
/* Return EOF if we
|
||||
* can't read more
|
||||
* data. */
|
||||
return ARCHIVE_EOF;
|
||||
return ret;
|
||||
}
|
||||
|
||||
skip_bits(rar, dbits - 4);
|
||||
@@ -3015,11 +3042,11 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
||||
/* dbits is one of [0,1,2,3] */
|
||||
int add;
|
||||
|
||||
if(ARCHIVE_OK != read_consume_bits(rar,
|
||||
p, dbits, &add)) {
|
||||
if(ARCHIVE_OK != (ret = read_consume_bits(a, rar,
|
||||
p, dbits, &add))) {
|
||||
/* Return EOF if we can't read
|
||||
* more data. */
|
||||
return ARCHIVE_EOF;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dist += add;
|
||||
@@ -3076,7 +3103,11 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
len = decode_code_length(rar, p, len_slot);
|
||||
len = decode_code_length(a, rar, p, len_slot);
|
||||
if (len == -1) {
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
rar->cstate.last_len = len;
|
||||
|
||||
if(ARCHIVE_OK != copy_string(a, len, dist))
|
||||
@@ -3600,6 +3631,16 @@ static int do_uncompress_file(struct archive_read* a) {
|
||||
rar->cstate.initialized = 1;
|
||||
}
|
||||
|
||||
/* Don't allow extraction if window_size is invalid. */
|
||||
if(rar->cstate.window_size == 0) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid window size declaration in this file");
|
||||
|
||||
/* This should never happen in valid files. */
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
if(rar->cstate.all_filters_applied == 1) {
|
||||
/* We use while(1) here, but standard case allows for just 1
|
||||
* iteration. The loop will iterate if process_block() didn't
|
||||
|
||||
@@ -173,6 +173,7 @@ struct fixup_entry {
|
||||
struct fixup_entry *next;
|
||||
struct archive_acl acl;
|
||||
mode_t mode;
|
||||
__LA_MODE_T filetype;
|
||||
int64_t atime;
|
||||
int64_t birthtime;
|
||||
int64_t mtime;
|
||||
@@ -357,6 +358,7 @@ struct archive_write_disk {
|
||||
|
||||
static int la_opendirat(int, const char *);
|
||||
static int la_mktemp(struct archive_write_disk *);
|
||||
static int la_verify_filetype(mode_t, __LA_MODE_T);
|
||||
static void fsobj_error(int *, struct archive_string *, int, const char *,
|
||||
const char *);
|
||||
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
|
||||
@@ -464,6 +466,39 @@ la_opendirat(int fd, const char *path) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
la_verify_filetype(mode_t mode, __LA_MODE_T filetype) {
|
||||
int ret = 0;
|
||||
|
||||
switch (filetype) {
|
||||
case AE_IFREG:
|
||||
ret = (S_ISREG(mode));
|
||||
break;
|
||||
case AE_IFDIR:
|
||||
ret = (S_ISDIR(mode));
|
||||
break;
|
||||
case AE_IFLNK:
|
||||
ret = (S_ISLNK(mode));
|
||||
break;
|
||||
case AE_IFSOCK:
|
||||
ret = (S_ISSOCK(mode));
|
||||
break;
|
||||
case AE_IFCHR:
|
||||
ret = (S_ISCHR(mode));
|
||||
break;
|
||||
case AE_IFBLK:
|
||||
ret = (S_ISBLK(mode));
|
||||
break;
|
||||
case AE_IFIFO:
|
||||
ret = (S_ISFIFO(mode));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
lazy_stat(struct archive_write_disk *a)
|
||||
{
|
||||
@@ -822,6 +857,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||
if (fe == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->filetype = archive_entry_filetype(entry);
|
||||
fe->fixup |= TODO_MODE_BASE;
|
||||
fe->mode = a->mode;
|
||||
}
|
||||
@@ -832,6 +868,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||
if (fe == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->filetype = archive_entry_filetype(entry);
|
||||
fe->mode = a->mode;
|
||||
fe->fixup |= TODO_TIMES;
|
||||
if (archive_entry_atime_is_set(entry)) {
|
||||
@@ -865,6 +902,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||
if (fe == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->filetype = archive_entry_filetype(entry);
|
||||
fe->fixup |= TODO_ACLS;
|
||||
archive_acl_copy(&fe->acl, archive_entry_acl(entry));
|
||||
}
|
||||
@@ -877,6 +915,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||
if (fe == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->filetype = archive_entry_filetype(entry);
|
||||
fe->mac_metadata = malloc(metadata_size);
|
||||
if (fe->mac_metadata != NULL) {
|
||||
memcpy(fe->mac_metadata, metadata,
|
||||
@@ -891,6 +930,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||
if (fe == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->filetype = archive_entry_filetype(entry);
|
||||
fe->fixup |= TODO_FFLAGS;
|
||||
/* TODO: Complete this.. defer fflags from below. */
|
||||
}
|
||||
@@ -2462,7 +2502,8 @@ _archive_write_disk_close(struct archive *_a)
|
||||
struct archive_write_disk *a = (struct archive_write_disk *)_a;
|
||||
struct fixup_entry *next, *p;
|
||||
struct stat st;
|
||||
int fd, ret;
|
||||
char *c;
|
||||
int fd, ret, openflags;
|
||||
|
||||
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
|
||||
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
|
||||
@@ -2475,24 +2516,70 @@ _archive_write_disk_close(struct archive *_a)
|
||||
while (p != NULL) {
|
||||
fd = -1;
|
||||
a->pst = NULL; /* Mark stat cache as out-of-date. */
|
||||
if (p->fixup &
|
||||
(TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) {
|
||||
fd = open(p->name,
|
||||
O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
/* If we cannot lstat, skip entry */
|
||||
if (lstat(p->name, &st) != 0)
|
||||
|
||||
/* We must strip trailing slashes from the path to avoid
|
||||
dereferencing symbolic links to directories */
|
||||
c = p->name;
|
||||
while (*c != '\0')
|
||||
c++;
|
||||
while (c != p->name && *(c - 1) == '/') {
|
||||
c--;
|
||||
*c = '\0';
|
||||
}
|
||||
|
||||
if (p->fixup == 0)
|
||||
goto skip_fixup_entry;
|
||||
else {
|
||||
/*
|
||||
* We need to verify if the type of the file
|
||||
* we are going to open matches the file type
|
||||
* of the fixup entry.
|
||||
*/
|
||||
openflags = O_BINARY | O_NOFOLLOW | O_RDONLY
|
||||
| O_CLOEXEC;
|
||||
#if defined(O_DIRECTORY)
|
||||
if (p->filetype == AE_IFDIR)
|
||||
openflags |= O_DIRECTORY;
|
||||
#endif
|
||||
fd = open(p->name, openflags);
|
||||
|
||||
#if defined(O_DIRECTORY)
|
||||
/*
|
||||
* If we support O_DIRECTORY and open was
|
||||
* successful we can skip the file type check
|
||||
* for directories. For other file types
|
||||
* we need to verify via fstat() or lstat()
|
||||
*/
|
||||
if (fd == -1 || p->filetype != AE_IFDIR) {
|
||||
#if HAVE_FSTAT
|
||||
if (fd > 0 && (
|
||||
fstat(fd, &st) != 0 ||
|
||||
la_verify_filetype(st.st_mode,
|
||||
p->filetype) == 0)) {
|
||||
goto skip_fixup_entry;
|
||||
} else
|
||||
#endif
|
||||
if (lstat(p->name, &st) != 0 ||
|
||||
la_verify_filetype(st.st_mode,
|
||||
p->filetype) == 0) {
|
||||
goto skip_fixup_entry;
|
||||
/*
|
||||
* If we deal with a symbolic link, mark
|
||||
* it in the fixup mode to ensure no
|
||||
* modifications are made to its target.
|
||||
*/
|
||||
if (S_ISLNK(st.st_mode)) {
|
||||
p->mode &= ~S_IFMT;
|
||||
p->mode |= S_IFLNK;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#if HAVE_FSTAT
|
||||
if (fd > 0 && (
|
||||
fstat(fd, &st) != 0 ||
|
||||
la_verify_filetype(st.st_mode,
|
||||
p->filetype) == 0)) {
|
||||
goto skip_fixup_entry;
|
||||
} else
|
||||
#endif
|
||||
if (lstat(p->name, &st) != 0 ||
|
||||
la_verify_filetype(st.st_mode,
|
||||
p->filetype) == 0) {
|
||||
goto skip_fixup_entry;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (p->fixup & TODO_TIMES) {
|
||||
set_times(a, fd, p->mode, p->name,
|
||||
@@ -2504,14 +2591,13 @@ _archive_write_disk_close(struct archive *_a)
|
||||
if (p->fixup & TODO_MODE_BASE) {
|
||||
#ifdef HAVE_FCHMOD
|
||||
if (fd >= 0)
|
||||
fchmod(fd, p->mode);
|
||||
fchmod(fd, p->mode & 07777);
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_LCHMOD
|
||||
lchmod(p->name, p->mode);
|
||||
lchmod(p->name, p->mode & 07777);
|
||||
#else
|
||||
if (!S_ISLNK(p->mode))
|
||||
chmod(p->name, p->mode);
|
||||
chmod(p->name, p->mode & 07777);
|
||||
#endif
|
||||
}
|
||||
if (p->fixup & TODO_ACLS)
|
||||
@@ -2664,7 +2750,7 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
|
||||
fe->next = a->fixup_list;
|
||||
a->fixup_list = fe;
|
||||
fe->fixup = 0;
|
||||
fe->mode = 0;
|
||||
fe->filetype = 0;
|
||||
fe->name = strdup(pathname);
|
||||
return (fe);
|
||||
}
|
||||
@@ -3787,6 +3873,7 @@ set_fflags(struct archive_write_disk *a)
|
||||
le = current_fixup(a, a->name);
|
||||
if (le == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
le->filetype = archive_entry_filetype(a->entry);
|
||||
le->fixup |= TODO_FFLAGS;
|
||||
le->fflags_set = set;
|
||||
/* Store the mode if it's not already there. */
|
||||
|
||||
@@ -1206,6 +1206,23 @@ DEFINE_TEST(test_read_format_rar5_different_window_size)
|
||||
EPILOGUE();
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_rar5_window_buf_and_size_desync)
|
||||
{
|
||||
/* oss fuzz 30442 */
|
||||
|
||||
char buf[4096];
|
||||
PROLOGUE("test_read_format_rar5_window_buf_and_size_desync.rar");
|
||||
|
||||
/* Return codes of those calls are ignored, because this sample file
|
||||
* is invalid. However, the unpacker shouldn't produce any SIGSEGV
|
||||
* errors during processing. */
|
||||
|
||||
(void) archive_read_next_header(a, &ae);
|
||||
while(0 < archive_read_data(a, buf, 46)) {}
|
||||
|
||||
EPILOGUE();
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_rar5_arm_filter_on_window_boundary)
|
||||
{
|
||||
char buf[4096];
|
||||
@@ -1271,3 +1288,39 @@ DEFINE_TEST(test_read_format_rar5_block_size_is_too_small)
|
||||
|
||||
EPILOGUE();
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_rar5_decode_number_out_of_bounds_read)
|
||||
{
|
||||
/* oss fuzz 30448 */
|
||||
|
||||
char buf[4096];
|
||||
PROLOGUE("test_read_format_rar5_decode_number_out_of_bounds_read.rar");
|
||||
|
||||
/* Return codes of those calls are ignored, because this sample file
|
||||
* is invalid. However, the unpacker shouldn't produce any SIGSEGV
|
||||
* errors during processing. */
|
||||
|
||||
(void) archive_read_next_header(a, &ae);
|
||||
while(0 < archive_read_data(a, buf, sizeof(buf))) {}
|
||||
|
||||
EPILOGUE();
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_rar5_bad_window_size_in_multiarchive_file)
|
||||
{
|
||||
/* oss fuzz 30459 */
|
||||
|
||||
char buf[4096];
|
||||
PROLOGUE("test_read_format_rar5_bad_window_sz_in_mltarc_file.rar");
|
||||
|
||||
/* This file is damaged, so those functions should return failure.
|
||||
* Additionally, SIGSEGV shouldn't be raised during execution
|
||||
* of those functions. */
|
||||
|
||||
(void) archive_read_next_header(a, &ae);
|
||||
while(0 < archive_read_data(a, buf, sizeof(buf))) {}
|
||||
(void) archive_read_next_header(a, &ae);
|
||||
while(0 < archive_read_data(a, buf, sizeof(buf))) {}
|
||||
|
||||
EPILOGUE();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
begin 644 test_read_format_rar5_bad_window_size_in_multiarchive_file.rar
|
||||
M4F%R(1H'`0`]/-[E`@$`_R`@1#[Z5P("`PL`("`@@"(`"?\@("#___\@("`@
|
||||
M("`@("`@("`@4X`J]`,"YR(#$($@("`@``$@("`@@<L0("`@("`@("`@("`@
|
||||
M("`@(""LCTJA`P$%`B`@`2!3@"KT`P+G(@,@("`@_P,!!B`@(/___R`@(('+
|
||||
5$"`OX2`@[.SL[.S_("`@("`@("`@
|
||||
`
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
begin 644 test_read_format_rar5_decode_number_out_of_bounds_read.rar
|
||||
M4F%R(1H'`0!3@"KT`P+G(@(0("`@@`L!!"`@("`@(($D_[BJ2"!::7!)210V
|
||||
M+0#ZF#)Q!`+>YPW_("`@("``_R````````````````````````````!__P``
|
||||
M``````!T72`@/EW_(/\@("`@("`@("`@("`@("`@("`@("`@("`@(/\@("`@
|
||||
M("`@("#_("`@("`@("`@("`@("`@("`@("`@("`@("#_("`@("`@("`@_R`@
|
||||
M("`@("`@("`@("`@("`@("`@("`@("`@_R`@("`@("`@(/\@("`@("`@("`@
|
||||
M("`@("`@("`@("`@("`@(/\@("`@("`@("#_("`@("`@("`@("`@("`@("`@
|
||||
E("`@("`@("#_("`@("`@("`@_R`@("`@("`@("`@("`@("`@(```
|
||||
`
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
begin 644 test_read_format_rar5_window_buf_and_size_desync.rar
|
||||
M4F%R(1H'`0`]/-[E`@$`_P$`1#[Z5P("`PL``BXB"?\`!(@B@0`)6.-AF?_1
|
||||
M^0DI&0GG(F%R(0<:)`!3@"KT`P+G(@O_X[\``#&``(?!!0$$[:L``$.M*E)A
|
||||
M<B$`O<\>P0";/P1%``A*2DI*2DYQ<6TN9'%*2DI*2DI*``!D<F--``````"Z
|
||||
MNC*ZNKJZNFYO=&%I;+JZNKJZNKJZOKJZ.KJZNKJZNKKZU@4%````0$!`0$!`
|
||||
M0$!`0$!`0$!`0$#_________/T#`0$!`0$!`-UM`0$!`0$!`0$!`0$!`0$!`
|
||||
M0$!`0'!,J+:O!IZ-WN4'@`!3*F0`````````````````````````````````
|
||||
M``````````````#T`P)287(A&@<!`%.`*O0#`N<B`_,F@`'[__\``(`4`01S
|
||||
J'`/H/O\H@?\D`#O9GIZ>GN<B"_]%``(``&1RGIZ>GIZ>8_^>GE/_``!.
|
||||
`
|
||||
end
|
||||
@@ -47,26 +47,50 @@ DEFINE_TEST(test_write_disk_fixup)
|
||||
/*
|
||||
* Create a file
|
||||
*/
|
||||
assertMakeFile("victim", 0600, "a");
|
||||
assertMakeFile("file", 0600, "a");
|
||||
|
||||
/*
|
||||
* Create a directory
|
||||
*/
|
||||
assertMakeDir("dir", 0700);
|
||||
|
||||
/*
|
||||
* Create a directory and a symlink with the same name
|
||||
*/
|
||||
|
||||
/* Directory: dir */
|
||||
/* Directory: dir1 */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir");
|
||||
archive_entry_set_mode(ae, AE_IFDIR | 0606);
|
||||
archive_entry_copy_pathname(ae, "dir1/");
|
||||
archive_entry_set_mode(ae, AE_IFDIR | 0555);
|
||||
assertEqualIntA(ad, 0, archive_write_header(ad, ae));
|
||||
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* Symbolic Link: dir -> foo */
|
||||
/* Directory: dir2 */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir2/");
|
||||
archive_entry_set_mode(ae, AE_IFDIR | 0555);
|
||||
assertEqualIntA(ad, 0, archive_write_header(ad, ae));
|
||||
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* Symbolic Link: dir1 -> dir */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir");
|
||||
archive_entry_copy_pathname(ae, "dir1");
|
||||
archive_entry_set_mode(ae, AE_IFLNK | 0777);
|
||||
archive_entry_set_size(ae, 0);
|
||||
archive_entry_copy_symlink(ae, "victim");
|
||||
archive_entry_copy_symlink(ae, "dir");
|
||||
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
|
||||
if (r >= ARCHIVE_WARN)
|
||||
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* Symbolic Link: dir2 -> file */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir2");
|
||||
archive_entry_set_mode(ae, AE_IFLNK | 0777);
|
||||
archive_entry_set_size(ae, 0);
|
||||
archive_entry_copy_symlink(ae, "file");
|
||||
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
|
||||
if (r >= ARCHIVE_WARN)
|
||||
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
|
||||
@@ -75,7 +99,9 @@ DEFINE_TEST(test_write_disk_fixup)
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_free(ad));
|
||||
|
||||
/* Test the entries on disk. */
|
||||
assertIsSymlink("dir", "victim", 0);
|
||||
assertFileMode("victim", 0600);
|
||||
assertIsSymlink("dir1", "dir", 0);
|
||||
assertIsSymlink("dir2", "file", 0);
|
||||
assertFileMode("dir", 0700);
|
||||
assertFileMode("file", 0600);
|
||||
#endif
|
||||
}
|
||||
Reference in new issue
Block a user