libarchive: merge from vendor branch

libarchive 3.8.7

Important bugfixes:
 #2871 libarchive: fix handling of option failures
 #2897 iso9660: fix undefined behavior
 #2898 RAR: fix LZSS window size mismatch after PPMd block
 #2900 CAB: fix NULL pointer dereference during skip
 #2911 libarchive: do not continue with truncated numbers
 #2919 CAB: Fix Heap OOB Write in CAB LZX decoder
 #2934 iso9660: fix posibble heap buffer overflow on 32-bit systems
 #2939 cpio: Fix -R memory leak
 #2947 libarchive: lzop and grzip filter support

Important bugfixes between 3.8.5 and 3.8.6:
 #2860 bsdunzip: fix ISO week year and Gregorian year confusion
 #2864 7zip: ix SEGV in check_7zip_header_in_sfx via ELF offset validation
 #2875 7zip: fix out-of-bounds access on ELF 64-bit header
 #2877 RAR5 reader: fix infinite loop in rar5 decompression
 #2878 mtree reader: Fix file descriptor leak in mtree parser cleanup
       (CWE-775)
 #2892 RAR5 reader: fix potential memory leak
 #2893 RAR5: fix SIGSEGV when archive_read_support_format_rar5 is called
       twice
 #2895 CAB reader: fix memory leak on repeated calls to
       archive_read_support_format_cab

Obtained from:	libarchive
Vendor commit:	ded82291ab41d5e355831b96b0e1ff49e24d8939
MFC after:	1 week
This commit is contained in:
Martin Matuska
2026-04-13 15:47:17 +02:00
95 changed files with 3021 additions and 374 deletions
+4
View File
@@ -1,3 +1,7 @@
Apr 13, 2026: libarchive 3.8.7 released
Mar 10, 2026: libarchive 3.8.6 released
Jan 05, 2026: libarchive 3.8.5 released Jan 05, 2026: libarchive 3.8.5 released
Dec 01, 2025: libarchive 3.8.4 released Dec 01, 2025: libarchive 3.8.4 released
+6 -3
View File
@@ -37,10 +37,13 @@ The top-level directory contains the following information files:
* **CMakeLists.txt** - input for "cmake" build tool, see INSTALL * **CMakeLists.txt** - input for "cmake" build tool, see INSTALL
* **configure** - configuration script, see INSTALL for details. If your copy of the source lacks a `configure` script, you can try to construct it by running the script in `build/autogen.sh` (or use `cmake`). * **configure** - configuration script, see INSTALL for details. If your copy of the source lacks a `configure` script, you can try to construct it by running the script in `build/autogen.sh` (or use `cmake`).
The following files in the top-level directory are used by the 'configure' script: The following files in the top-level directory are related to the 'configure' script and are only needed by maintainers:
* `Makefile.am`, `aclocal.m4`, `configure.ac` - used to build this distribution, only needed by maintainers * `configure.ac` - used (by autoconf) to build the configure script and related files
* `Makefile.in`, `config.h.in` - templates used by configure script * `Makefile.am` - used (by automake) to generate Makefile.in
* `aclocal.m4` - auto-generated file (created by aclocal) used to build the configure script
* `Makefile.in` - auto-generated template (created by automake) used by the configure script to create Makefile
* `config.h.in` - auto-generated template (created by autoheader) used by the configure script to create config.h
## Documentation ## Documentation
+11 -4
View File
@@ -11,6 +11,9 @@
#ifdef HAVE_ERRNO_H #ifdef HAVE_ERRNO_H
#include <errno.h> #include <errno.h>
#endif #endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_GRP_H #ifdef HAVE_GRP_H
#include <grp.h> #include <grp.h>
#endif #endif
@@ -347,9 +350,10 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg)
owner->gid = pwent->pw_gid; owner->gid = pwent->pw_gid;
} else { } else {
char *end; char *end;
unsigned long val;
errno = 0; errno = 0;
owner->uid = (int)strtoul(user, &end, 10); val = strtoul(user, &end, 10);
if (errno || *end != '\0') { if (errno || *end != '\0' || val > (unsigned)INT_MAX) {
snprintf(errbuff, sizeof(errbuff), snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup user ``%s''", user); "Couldn't lookup user ``%s''", user);
errbuff[sizeof(errbuff) - 1] = '\0'; errbuff[sizeof(errbuff) - 1] = '\0';
@@ -357,6 +361,7 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg)
*errmsg = errbuff; *errmsg = errbuff;
return (-1); return (-1);
} }
owner->uid = (int)val;
} }
free(user); free(user);
} }
@@ -373,15 +378,17 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg)
} }
} else { } else {
char *end; char *end;
unsigned long val;
errno = 0; errno = 0;
owner->gid = (int)strtoul(g, &end, 10); val = strtoul(g, &end, 10);
if (errno || *end != '\0') { if (errno || *end != '\0' || val > (unsigned)INT_MAX) {
snprintf(errbuff, sizeof(errbuff), snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup group ``%s''", g); "Couldn't lookup group ``%s''", g);
errbuff[sizeof(errbuff) - 1] = '\0'; errbuff[sizeof(errbuff) - 1] = '\0';
*errmsg = errbuff; *errmsg = errbuff;
return (-1); return (-1);
} }
owner->gid = (int)val;
} }
} }
return (0); return (0);
+66 -55
View File
@@ -8,6 +8,8 @@
#include "cpio_platform.h" #include "cpio_platform.h"
#include "lafe_getline.h"
#include <sys/types.h> #include <sys/types.h>
#include <archive.h> #include <archive.h>
#include <archive_entry.h> #include <archive_entry.h>
@@ -33,6 +35,9 @@
#ifdef HAVE_LOCALE_H #ifdef HAVE_LOCALE_H
#include <locale.h> #include <locale.h>
#endif #endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_PWD_H #ifdef HAVE_PWD_H
#include <pwd.h> #include <pwd.h>
#endif #endif
@@ -83,7 +88,7 @@ struct name_cache {
static int extract_data(struct archive *, struct archive *); static int extract_data(struct archive *, struct archive *);
const char * cpio_i64toa(int64_t); const char * cpio_i64toa(int64_t);
static const char *cpio_rename(const char *name); static void cpio_rename(struct archive_entry *);
static int entry_to_archive(struct cpio *, struct archive_entry *); static int entry_to_archive(struct cpio *, struct archive_entry *);
static int file_to_archive(struct cpio *, const char *); static int file_to_archive(struct cpio *, const char *);
static void free_cache(struct name_cache *cache); static void free_cache(struct name_cache *cache);
@@ -110,19 +115,16 @@ static void passphrase_free(char *);
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
static char buff[16384];
struct cpio _cpio; /* Allocated on stack. */ struct cpio _cpio; /* Allocated on stack. */
struct cpio *cpio; struct cpio *cpio;
struct cpio_owner owner; struct cpio_owner owner;
const char *errmsg; const char *errmsg;
char *tptr; char *tptr;
int opt, t; int opt;
long t;
cpio = &_cpio; cpio = &_cpio;
memset(cpio, 0, sizeof(*cpio)); memset(cpio, 0, sizeof(*cpio));
cpio->buff = buff;
cpio->buff_size = sizeof(buff);
#if defined(HAVE_SIGACTION) #if defined(HAVE_SIGACTION)
{ {
@@ -204,13 +206,13 @@ main(int argc, char *argv[])
case 'C': /* NetBSD/OpenBSD */ case 'C': /* NetBSD/OpenBSD */
errno = 0; errno = 0;
tptr = NULL; tptr = NULL;
t = (int)strtol(cpio->argument, &tptr, 10); t = strtol(cpio->argument, &tptr, 10);
if (errno || t <= 0 || *(cpio->argument) == '\0' || if (errno || t <= 0 || t > INT_MAX || *(cpio->argument) == '\0' ||
tptr == NULL || *tptr != '\0') { tptr == NULL || *tptr != '\0') {
lafe_errc(1, 0, "Invalid blocksize: %s", lafe_errc(1, 0, "Invalid blocksize: %s",
cpio->argument); cpio->argument);
} }
cpio->bytes_per_block = t; cpio->bytes_per_block = (int)t;
break; break;
case 'c': /* POSIX 1997 */ case 'c': /* POSIX 1997 */
cpio->format = "odc"; cpio->format = "odc";
@@ -222,7 +224,7 @@ main(int argc, char *argv[])
if (archive_match_include_pattern_from_file( if (archive_match_include_pattern_from_file(
cpio->matching, cpio->argument, cpio->matching, cpio->argument,
cpio->option_null) != ARCHIVE_OK) cpio->option_null) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(cpio->matching)); archive_error_string(cpio->matching));
break; break;
case 'F': /* NetBSD/OpenBSD/GNU cpio */ case 'F': /* NetBSD/OpenBSD/GNU cpio */
@@ -231,7 +233,7 @@ main(int argc, char *argv[])
case 'f': /* POSIX 1997 */ case 'f': /* POSIX 1997 */
if (archive_match_exclude_pattern(cpio->matching, if (archive_match_exclude_pattern(cpio->matching,
cpio->argument) != ARCHIVE_OK) cpio->argument) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(cpio->matching)); archive_error_string(cpio->matching));
break; break;
case OPTION_GRZIP: case OPTION_GRZIP:
@@ -247,7 +249,7 @@ main(int argc, char *argv[])
cpio->filename = cpio->argument; cpio->filename = cpio->argument;
break; break;
case 'i': /* POSIX 1997 */ case 'i': /* POSIX 1997 */
if (cpio->mode != '\0') if (cpio->mode != '\0' && cpio->mode != opt)
lafe_errc(1, 0, lafe_errc(1, 0,
"Cannot use both -i and -%c", cpio->mode); "Cannot use both -i and -%c", cpio->mode);
cpio->mode = opt; cpio->mode = opt;
@@ -289,13 +291,13 @@ main(int argc, char *argv[])
cpio->filename = cpio->argument; cpio->filename = cpio->argument;
break; break;
case 'o': /* POSIX 1997 */ case 'o': /* POSIX 1997 */
if (cpio->mode != '\0') if (cpio->mode != '\0' && cpio->mode != opt)
lafe_errc(1, 0, lafe_errc(1, 0,
"Cannot use both -o and -%c", cpio->mode); "Cannot use both -o and -%c", cpio->mode);
cpio->mode = opt; cpio->mode = opt;
break; break;
case 'p': /* POSIX 1997 */ case 'p': /* POSIX 1997 */
if (cpio->mode != '\0') if (cpio->mode != '\0' && cpio->mode != opt)
lafe_errc(1, 0, lafe_errc(1, 0,
"Cannot use both -p and -%c", cpio->mode); "Cannot use both -p and -%c", cpio->mode);
cpio->mode = opt; cpio->mode = opt;
@@ -316,17 +318,21 @@ main(int argc, char *argv[])
if (owner_parse(cpio->argument, &owner, &errmsg) != 0) { if (owner_parse(cpio->argument, &owner, &errmsg) != 0) {
if (!errmsg) if (!errmsg)
errmsg = "Error parsing owner"; errmsg = "Error parsing owner";
lafe_warnc(-1, "%s", errmsg); lafe_warnc(0, "%s", errmsg);
usage(); usage();
} }
if (owner.uid != -1) if (owner.uid != -1)
cpio->uid_override = owner.uid; cpio->uid_override = owner.uid;
if (owner.uname != NULL) if (owner.uname != NULL) {
free(cpio->uname_override);
cpio->uname_override = owner.uname; cpio->uname_override = owner.uname;
}
if (owner.gid != -1) if (owner.gid != -1)
cpio->gid_override = owner.gid; cpio->gid_override = owner.gid;
if (owner.gname != NULL) if (owner.gname != NULL) {
free(cpio->gname_override);
cpio->gname_override = owner.gname; cpio->gname_override = owner.gname;
}
break; break;
case 'r': /* POSIX 1997 */ case 'r': /* POSIX 1997 */
cpio->option_rename = 1; cpio->option_rename = 1;
@@ -409,7 +415,7 @@ main(int argc, char *argv[])
while (*cpio->argv != NULL) { while (*cpio->argv != NULL) {
if (archive_match_include_pattern(cpio->matching, if (archive_match_include_pattern(cpio->matching,
*cpio->argv) != ARCHIVE_OK) *cpio->argv) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(cpio->matching)); archive_error_string(cpio->matching));
--cpio->argc; --cpio->argc;
++cpio->argv; ++cpio->argv;
@@ -427,7 +433,7 @@ main(int argc, char *argv[])
break; break;
default: default:
lafe_errc(1, 0, lafe_errc(1, 0,
"Must specify at least one of -i, -o, or -p"); "Must specify one of -i, -o, or -p");
} }
archive_match_free(cpio->matching); archive_match_free(cpio->matching);
@@ -524,7 +530,7 @@ mode_out(struct cpio *cpio)
int r; int r;
if (cpio->option_append) if (cpio->option_append)
lafe_errc(1, 0, "Append mode not yet supported."); lafe_errc(1, 0, "Append mode not yet supported");
cpio->archive_read_disk = archive_read_disk_new(); cpio->archive_read_disk = archive_read_disk_new();
if (cpio->archive_read_disk == NULL) if (cpio->archive_read_disk == NULL)
@@ -638,7 +644,7 @@ mode_out(struct cpio *cpio)
int64_t blocks = int64_t blocks =
(archive_filter_bytes(cpio->archive, 0) + 511) (archive_filter_bytes(cpio->archive, 0) + 511)
/ 512; / 512;
fprintf(stderr, "%lu %s\n", (unsigned long)blocks, fprintf(stderr, "%lld %s\n", (long long)blocks,
blocks == 1 ? "block" : "blocks"); blocks == 1 ? "block" : "blocks");
} }
archive_write_free(cpio->archive); archive_write_free(cpio->archive);
@@ -696,7 +702,6 @@ remove_leading_slash(const char *p)
static int static int
file_to_archive(struct cpio *cpio, const char *srcpath) file_to_archive(struct cpio *cpio, const char *srcpath)
{ {
const char *destpath;
struct archive_entry *entry, *spare; struct archive_entry *entry, *spare;
size_t len; size_t len;
int r; int r;
@@ -738,7 +743,6 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
* pass mode or the name that will go into the archive in * pass mode or the name that will go into the archive in
* output mode. * output mode.
*/ */
destpath = srcpath;
if (cpio->destdir) { if (cpio->destdir) {
len = cpio->destdir_len + strlen(srcpath) + 8; len = cpio->destdir_len + strlen(srcpath) + 8;
if (len >= cpio->pass_destpath_alloc) { if (len >= cpio->pass_destpath_alloc) {
@@ -754,15 +758,17 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
} }
strcpy(cpio->pass_destpath, cpio->destdir); strcpy(cpio->pass_destpath, cpio->destdir);
strcat(cpio->pass_destpath, remove_leading_slash(srcpath)); strcat(cpio->pass_destpath, remove_leading_slash(srcpath));
destpath = cpio->pass_destpath; archive_entry_set_pathname(entry, cpio->pass_destpath);
} else {
archive_entry_set_pathname(entry, srcpath);
} }
if (cpio->option_rename) if (cpio->option_rename)
destpath = cpio_rename(destpath); cpio_rename(entry);
if (destpath == NULL) {
if (archive_entry_pathname(entry) == NULL) {
archive_entry_free(entry); archive_entry_free(entry);
return (0); return (0);
} }
archive_entry_copy_pathname(entry, destpath);
/* /*
* If we're trying to preserve hardlinks, match them here. * If we're trying to preserve hardlinks, match them here.
@@ -791,7 +797,6 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
const char *destpath = archive_entry_pathname(entry); const char *destpath = archive_entry_pathname(entry);
const char *srcpath = archive_entry_sourcepath(entry); const char *srcpath = archive_entry_sourcepath(entry);
int fd = -1; int fd = -1;
ssize_t bytes_read;
int r; int r;
/* Print out the destination name to the user. */ /* Print out the destination name to the user. */
@@ -869,21 +874,23 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
exit(1); exit(1);
if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) { if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) {
bytes_read = read(fd, cpio->buff, (unsigned)cpio->buff_size); static char buff[16384];
ssize_t bytes_read;
bytes_read = read(fd, buff, sizeof(buff));
while (bytes_read > 0) { while (bytes_read > 0) {
ssize_t bytes_write; ssize_t bytes_write;
bytes_write = archive_write_data(cpio->archive, bytes_write = archive_write_data(cpio->archive,
cpio->buff, bytes_read); buff, bytes_read);
if (bytes_write < 0) if (bytes_write < 0)
lafe_errc(1, archive_errno(cpio->archive), lafe_errc(1, archive_errno(cpio->archive),
"%s", archive_error_string(cpio->archive)); "%s", archive_error_string(cpio->archive));
if (bytes_write < bytes_read) { if (bytes_write < bytes_read) {
lafe_warnc(0, lafe_warnc(0,
"Truncated write; file may have " "Truncated write; file may have "
"grown while being archived."); "grown while being archived");
} }
bytes_read = read(fd, cpio->buff, bytes_read = read(fd, buff, sizeof(buff));
(unsigned)cpio->buff_size);
} }
} }
@@ -997,10 +1004,8 @@ mode_in(struct cpio *cpio)
} }
if (archive_match_path_excluded(cpio->matching, entry)) if (archive_match_path_excluded(cpio->matching, entry))
continue; continue;
if (cpio->option_rename) { if (cpio->option_rename)
destpath = cpio_rename(archive_entry_pathname(entry)); cpio_rename(entry);
archive_entry_set_pathname(entry, destpath);
} else
destpath = archive_entry_pathname(entry); destpath = archive_entry_pathname(entry);
if (destpath == NULL) if (destpath == NULL)
continue; continue;
@@ -1040,7 +1045,7 @@ mode_in(struct cpio *cpio)
if (!cpio->quiet) { if (!cpio->quiet) {
int64_t blocks = (archive_filter_bytes(a, 0) + 511) int64_t blocks = (archive_filter_bytes(a, 0) + 511)
/ 512; / 512;
fprintf(stderr, "%lu %s\n", (unsigned long)blocks, fprintf(stderr, "%lld %s\n", (long long)blocks,
blocks == 1 ? "block" : "blocks"); blocks == 1 ? "block" : "blocks");
} }
archive_read_free(a); archive_read_free(a);
@@ -1125,7 +1130,7 @@ mode_list(struct cpio *cpio)
if (!cpio->quiet) { if (!cpio->quiet) {
int64_t blocks = (archive_filter_bytes(a, 0) + 511) int64_t blocks = (archive_filter_bytes(a, 0) + 511)
/ 512; / 512;
fprintf(stderr, "%lu %s\n", (unsigned long)blocks, fprintf(stderr, "%lld %s\n", (long long)blocks,
blocks == 1 ? "block" : "blocks"); blocks == 1 ? "block" : "blocks");
} }
archive_read_free(a); archive_read_free(a);
@@ -1292,54 +1297,60 @@ mode_pass(struct cpio *cpio, const char *destdir)
* that an input of '.' means the name should be unchanged. GNU cpio * that an input of '.' means the name should be unchanged. GNU cpio
* treats '.' as a literal new name. * treats '.' as a literal new name.
*/ */
static const char * void
cpio_rename(const char *name) cpio_rename(struct archive_entry *entry)
{ {
static char buff[1024]; char *buff = NULL, *p, *ret = NULL;
FILE *t; FILE *t;
char *p, *ret; size_t n = 0;
ssize_t r;
#if defined(_WIN32) && !defined(__CYGWIN__) #if defined(_WIN32) && !defined(__CYGWIN__)
FILE *to; FILE *to;
t = fopen("CONIN$", "r"); t = fopen("CONIN$", "r");
if (t == NULL) if (t == NULL)
return (name); return;
to = fopen("CONOUT$", "w"); to = fopen("CONOUT$", "w");
if (to == NULL) { if (to == NULL) {
fclose(t); fclose(t);
return (name); return;
} }
fprintf(to, "%s (Enter/./(new name))? ", name); fprintf(to, "%s (Enter/./(new name))? ", archive_entry_pathname(entry));
fclose(to); fclose(to);
#else #else
t = fopen("/dev/tty", "r+"); t = fopen("/dev/tty", "r+");
if (t == NULL) if (t == NULL)
return (name); return;
fprintf(t, "%s (Enter/./(new name))? ", name); fprintf(t, "%s (Enter/./(new name))? ", archive_entry_pathname(entry));
fflush(t); fflush(t);
#endif #endif
p = fgets(buff, sizeof(buff), t); r = getline(&buff, &n, t);
fclose(t); fclose(t);
if (p == NULL) if (r < 1)
/* End-of-file is a blank line. */ /* End-of-file is a blank line. */
return (NULL); goto done;
p = buff;
while (*p == ' ' || *p == '\t') while (*p == ' ' || *p == '\t')
++p; ++p;
if (*p == '\n' || *p == '\0') if (*p == '\n' || *p == '\0')
/* Empty line. */ /* Empty line. */
return (NULL); goto done;
if (*p == '.' && p[1] == '\n') if (*p == '.' && p[1] == '\n') {
/* Single period preserves original name. */ /* Single period preserves original name. */
return (name); free(buff);
return;
}
ret = p; ret = p;
/* Trim the final newline. */ /* Trim the final newline. */
while (*p != '\0' && *p != '\n') while (*p != '\0' && *p != '\n')
++p; ++p;
/* Overwrite the final \n with a null character. */ /* Overwrite the final \n with a null character. */
*p = '\0'; *p = '\0';
return (ret); done:
archive_entry_set_pathname(entry, ret);
free(buff);
} }
static void static void
-2
View File
@@ -71,8 +71,6 @@ struct cpio {
/* Work data. */ /* Work data. */
struct archive *matching; struct archive *matching;
char *buff;
size_t buff_size;
char *ppbuff; char *ppbuff;
}; };
@@ -6,6 +6,13 @@
*/ */
#include "test.h" #include "test.h"
#ifdef HAVE_GETEUID
#define getuid() geteuid()
#endif
#ifdef HAVE_GETEGID
#define getgid() getegid()
#endif
/* Number of bytes needed to pad 'n' to multiple of 'block', assuming /* Number of bytes needed to pad 'n' to multiple of 'block', assuming
* that 'block' is a power of two. This trick can be more easily * that 'block' is a power of two. This trick can be more easily
* remembered as -n & (block - 1), but many compilers quite reasonably * remembered as -n & (block - 1), but many compilers quite reasonably
+2 -2
View File
@@ -34,7 +34,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108. * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/ */
/* Note: Compiler will complain if this does not match archive_entry.h! */ /* Note: Compiler will complain if this does not match archive_entry.h! */
#define ARCHIVE_VERSION_NUMBER 3008005 #define ARCHIVE_VERSION_NUMBER 3008007
#include <sys/stat.h> #include <sys/stat.h>
#include <stddef.h> /* for wchar_t */ #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. * Textual name/version of the library, useful for version displays.
*/ */
#define ARCHIVE_VERSION_ONLY_STRING "3.8.5" #define ARCHIVE_VERSION_ONLY_STRING "3.8.7"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void); __LA_DECL const char * archive_version_string(void);
+5 -1
View File
@@ -1256,8 +1256,12 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
tag = 0; tag = 0;
s = field[n].start; s = field[n].start;
st = field[n].start + 1;
len = field[n].end - field[n].start; len = field[n].end - field[n].start;
if (len == 0) {
ret = ARCHIVE_WARN;
continue;
}
st = s + 1;
switch (*s) { switch (*s) {
case L'u': case L'u':
@@ -148,14 +148,14 @@ __archive_check_magic(struct archive *a, unsigned int magic,
if (!handle_type) { if (!handle_type) {
errmsg("PROGRAMMER ERROR: Function "); errmsg("PROGRAMMER ERROR: Function ");
errmsg(function); errmsg(function);
errmsg(" invoked with invalid archive handle.\n"); errmsg(" invoked with invalid archive handle\n");
diediedie(); diediedie();
} }
if (a->magic != magic) { if (a->magic != magic) {
archive_set_error(a, -1, archive_set_error(a, -1,
"PROGRAMMER ERROR: Function '%s' invoked" "PROGRAMMER ERROR: Function '%s' invoked"
" on '%s' archive object, which is not supported.", " on '%s' archive object, which is not supported",
function, function,
handle_type); handle_type);
a->state = ARCHIVE_STATE_FATAL; a->state = ARCHIVE_STATE_FATAL;
@@ -109,6 +109,10 @@ typedef struct {
#include <nettle/version.h> #include <nettle/version.h>
#define ARCHIVE_CRYPTOR_USE_NETTLE 1 #define ARCHIVE_CRYPTOR_USE_NETTLE 1
#ifndef AES_MAX_KEY_SIZE
#define AES_MAX_KEY_SIZE AES256_KEY_SIZE
#endif
typedef struct { typedef struct {
#if NETTLE_VERSION_MAJOR < 3 #if NETTLE_VERSION_MAJOR < 3
struct aes_ctx ctx; struct aes_ctx ctx;
@@ -28,7 +28,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED #define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */ /* Note: Compiler will complain if this does not match archive.h! */
#define ARCHIVE_VERSION_NUMBER 3008005 #define ARCHIVE_VERSION_NUMBER 3008007
/* /*
* Note: archive_entry.h is for use outside of libarchive; the * Note: archive_entry.h is for use outside of libarchive; the
@@ -198,6 +198,7 @@ static void __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
} }
#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H) #elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
#include <nettle/version.h>
static int static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
@@ -216,7 +217,12 @@ __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
static void static void
__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
{ {
#if NETTLE_VERSION_MAJOR < 4
hmac_sha1_digest(ctx, (unsigned)*out_len, out); hmac_sha1_digest(ctx, (unsigned)*out_len, out);
#else
hmac_sha1_digest(ctx, out);
*out_len = SHA1_DIGEST_SIZE;
#endif
} }
static void static void
@@ -90,6 +90,8 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons
if (r2 == ARCHIVE_FATAL) if (r2 == ARCHIVE_FATAL)
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
if (r1 == ARCHIVE_WARN - 1)
return r2;
if (r2 == ARCHIVE_WARN -1) if (r2 == ARCHIVE_WARN -1)
return r1; return r1;
return r1 > r2 ? r1 : r2; return r1 > r2 ? r1 : r2;
@@ -202,7 +202,7 @@ pm(const char *p, const char *s, int flags)
if (*p == '\0') if (*p == '\0')
return (1); return (1);
while (*s) { while (*s) {
if (archive_pathmatch(p, s, flags)) if (pm(p, s, flags))
return (1); return (1);
++s; ++s;
} }
@@ -307,7 +307,7 @@ pm_w(const wchar_t *p, const wchar_t *s, int flags)
if (*p == L'\0') if (*p == L'\0')
return (1); return (1);
while (*s) { while (*s) {
if (archive_pathmatch_w(p, s, flags)) if (pm_w(p, s, flags))
return (1); return (1);
++s; ++s;
} }
+11 -11
View File
@@ -61,7 +61,7 @@ typedef struct CPpmd8_Node_
#define EMPTY_NODE 0xFFFFFFFF #define EMPTY_NODE 0xFFFFFFFF
void Ppmd8_Construct(CPpmd8 *p) static void Ppmd8_Construct(CPpmd8 *p)
{ {
unsigned i, k, m; unsigned i, k, m;
@@ -89,14 +89,14 @@ void Ppmd8_Construct(CPpmd8 *p)
} }
} }
void Ppmd8_Free(CPpmd8 *p) static void Ppmd8_Free(CPpmd8 *p)
{ {
free(p->Base); free(p->Base);
p->Size = 0; p->Size = 0;
p->Base = 0; p->Base = 0;
} }
Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size) static Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size)
{ {
if (p->Base == 0 || p->Size != size) if (p->Base == 0 || p->Size != size)
{ {
@@ -407,7 +407,7 @@ static void RestartModel(CPpmd8 *p)
} }
} }
void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod) static void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod)
{ {
p->MaxOrder = maxOrder; p->MaxOrder = maxOrder;
p->RestoreMethod = restoreMethod; p->RestoreMethod = restoreMethod;
@@ -1042,7 +1042,7 @@ static void Rescale(CPpmd8 *p)
p->FoundState = STATS(p->MinContext); p->FoundState = STATS(p->MinContext);
} }
CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq) static CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)
{ {
CPpmd_See *see; CPpmd_See *see;
if (p->MinContext->NumStats != 0xFF) if (p->MinContext->NumStats != 0xFF)
@@ -1078,7 +1078,7 @@ static void NextContext(CPpmd8 *p)
} }
} }
void Ppmd8_Update1(CPpmd8 *p) static void Ppmd8_Update1(CPpmd8 *p)
{ {
CPpmd_State *s = p->FoundState; CPpmd_State *s = p->FoundState;
s->Freq += 4; s->Freq += 4;
@@ -1093,7 +1093,7 @@ void Ppmd8_Update1(CPpmd8 *p)
NextContext(p); NextContext(p);
} }
void Ppmd8_Update1_0(CPpmd8 *p) static void Ppmd8_Update1_0(CPpmd8 *p)
{ {
p->PrevSuccess = (2 * p->FoundState->Freq >= p->MinContext->SummFreq); p->PrevSuccess = (2 * p->FoundState->Freq >= p->MinContext->SummFreq);
p->RunLength += p->PrevSuccess; p->RunLength += p->PrevSuccess;
@@ -1103,7 +1103,7 @@ void Ppmd8_Update1_0(CPpmd8 *p)
NextContext(p); NextContext(p);
} }
void Ppmd8_UpdateBin(CPpmd8 *p) static void Ppmd8_UpdateBin(CPpmd8 *p)
{ {
p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 196)); p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 196));
p->PrevSuccess = 1; p->PrevSuccess = 1;
@@ -1111,7 +1111,7 @@ void Ppmd8_UpdateBin(CPpmd8 *p)
NextContext(p); NextContext(p);
} }
void Ppmd8_Update2(CPpmd8 *p) static void Ppmd8_Update2(CPpmd8 *p)
{ {
p->MinContext->SummFreq += 4; p->MinContext->SummFreq += 4;
if ((p->FoundState->Freq += 4) > MAX_FREQ) if ((p->FoundState->Freq += 4) > MAX_FREQ)
@@ -1127,7 +1127,7 @@ This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
Bool Ppmd8_RangeDec_Init(CPpmd8 *p) static Bool Ppmd8_RangeDec_Init(CPpmd8 *p)
{ {
unsigned i; unsigned i;
p->Low = 0; p->Low = 0;
@@ -1161,7 +1161,7 @@ static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
#define MASK(sym) ((signed char *)charMask)[sym] #define MASK(sym) ((signed char *)charMask)[sym]
int Ppmd8_DecodeSymbol(CPpmd8 *p) static int Ppmd8_DecodeSymbol(CPpmd8 *p)
{ {
size_t charMask[256 / sizeof(size_t)]; size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 0) if (p->MinContext->NumStats != 0)
@@ -83,12 +83,6 @@ typedef struct
UInt16 BinSumm[25][64]; UInt16 BinSumm[25][64];
} CPpmd8; } CPpmd8;
void Ppmd8_Construct(CPpmd8 *p);
Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size);
void Ppmd8_Free(CPpmd8 *p);
void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod);
#define Ppmd8_WasAllocated(p) ((p)->Base != NULL)
/* ---------- Internal Functions ---------- */ /* ---------- Internal Functions ---------- */
@@ -104,30 +98,11 @@ extern const Byte PPMD8_kExpEscape[16];
#define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats))) #define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats)))
#endif #endif
void Ppmd8_Update1(CPpmd8 *p);
void Ppmd8_Update1_0(CPpmd8 *p);
void Ppmd8_Update2(CPpmd8 *p);
void Ppmd8_UpdateBin(CPpmd8 *p);
#define Ppmd8_GetBinSumm(p) \ #define Ppmd8_GetBinSumm(p) \
&p->BinSumm[p->NS2Indx[Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \ &p->BinSumm[p->NS2Indx[Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \
p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \ p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \
p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)] p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)]
CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale);
/* ---------- Decode ---------- */
Bool Ppmd8_RangeDec_Init(CPpmd8 *p);
#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
int Ppmd8_DecodeSymbol(CPpmd8 *p); /* returns: -1 as EndMarker, -2 as DataError */
/* ---------- Encode ---------- */
#define Ppmd8_RangeEnc_Init(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; }
void Ppmd8_RangeEnc_FlushData(CPpmd8 *p);
void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol); /* symbol = -1 means EndMarker */
typedef struct typedef struct
{ {
+6 -6
View File
@@ -171,7 +171,7 @@ static int64_t
client_skip_proxy(struct archive_read_filter *self, int64_t request) client_skip_proxy(struct archive_read_filter *self, int64_t request)
{ {
if (request < 0) if (request < 0)
__archive_errx(1, "Negative skip requested."); __archive_errx(1, "Negative skip requested");
if (request == 0) if (request == 0)
return 0; return 0;
@@ -379,7 +379,7 @@ archive_read_set_callback_data2(struct archive *_a, void *client_data,
if (a->client.dataset == NULL) if (a->client.dataset == NULL)
{ {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"No memory."); "No memory");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
a->client.nodes = 1; a->client.nodes = 1;
@@ -388,7 +388,7 @@ archive_read_set_callback_data2(struct archive *_a, void *client_data,
if (iindex > a->client.nodes - 1) if (iindex > a->client.nodes - 1)
{ {
archive_set_error(&a->archive, EINVAL, archive_set_error(&a->archive, EINVAL,
"Invalid index specified."); "Invalid index specified");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
a->client.dataset[iindex].data = client_data; a->client.dataset[iindex].data = client_data;
@@ -409,14 +409,14 @@ archive_read_add_callback_data(struct archive *_a, void *client_data,
"archive_read_add_callback_data"); "archive_read_add_callback_data");
if (iindex > a->client.nodes) { if (iindex > a->client.nodes) {
archive_set_error(&a->archive, EINVAL, archive_set_error(&a->archive, EINVAL,
"Invalid index specified."); "Invalid index specified");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
p = realloc(a->client.dataset, sizeof(*a->client.dataset) p = realloc(a->client.dataset, sizeof(*a->client.dataset)
* (++(a->client.nodes))); * (++(a->client.nodes)));
if (p == NULL) { if (p == NULL) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"No memory."); "No memory");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
a->client.dataset = (struct archive_read_data_node *)p; a->client.dataset = (struct archive_read_data_node *)p;
@@ -625,7 +625,7 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
r1 = archive_read_data_skip(&a->archive); r1 = archive_read_data_skip(&a->archive);
if (r1 == ARCHIVE_EOF) if (r1 == ARCHIVE_EOF)
archive_set_error(&a->archive, EIO, archive_set_error(&a->archive, EIO,
"Premature end-of-file."); "Premature end-of-file");
if (r1 == ARCHIVE_EOF || r1 == ARCHIVE_FATAL) { if (r1 == ARCHIVE_EOF || r1 == ARCHIVE_FATAL) {
a->archive.state = ARCHIVE_STATE_FATAL; a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
@@ -104,6 +104,10 @@ archive_read_append_filter(struct archive *_a, int code)
strcpy(str, "lrzip"); strcpy(str, "lrzip");
r1 = archive_read_support_filter_lrzip(_a); r1 = archive_read_support_filter_lrzip(_a);
break; break;
case ARCHIVE_FILTER_GRZIP:
strcpy(str, "grzip");
r1 = archive_read_support_filter_grzip(_a);
break;
default: default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Invalid filter code specified"); "Invalid filter code specified");
@@ -921,7 +921,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_path_excluded(a->matching, entry); r = archive_match_path_excluded(a->matching, entry);
if (r < 0) { if (r < 0) {
archive_set_error(&(a->archive), errno, archive_set_error(&(a->archive), errno,
"Failed : %s", archive_error_string(a->matching)); "%s", archive_error_string(a->matching));
return (r); return (r);
} }
if (r) { if (r) {
@@ -1035,7 +1035,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_time_excluded(a->matching, entry); r = archive_match_time_excluded(a->matching, entry);
if (r < 0) { if (r < 0) {
archive_set_error(&(a->archive), errno, archive_set_error(&(a->archive), errno,
"Failed : %s", archive_error_string(a->matching)); "%s", archive_error_string(a->matching));
return (r); return (r);
} }
if (r) { if (r) {
@@ -1061,7 +1061,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_owner_excluded(a->matching, entry); r = archive_match_owner_excluded(a->matching, entry);
if (r < 0) { if (r < 0) {
archive_set_error(&(a->archive), errno, archive_set_error(&(a->archive), errno,
"Failed : %s", archive_error_string(a->matching)); "%s", archive_error_string(a->matching));
return (r); return (r);
} }
if (r) { if (r) {
@@ -122,13 +122,14 @@ archive_read_open_filenames(struct archive *a, const char **filenames,
archive_clear_error(a); archive_clear_error(a);
do do
{ {
size_t len;
if (filename == NULL) if (filename == NULL)
filename = ""; filename = "";
mine = calloc(1, len = strlen(filename);
sizeof(*mine) + strlen(filename)); mine = calloc(1, sizeof(*mine) + len);
if (mine == NULL) if (mine == NULL)
goto no_memory; goto no_memory;
strcpy(mine->filename.m, filename); memcpy(mine->filename.m, filename, len + 1);
mine->block_size = block_size; mine->block_size = block_size;
mine->fd = -1; mine->fd = -1;
mine->buffer = NULL; mine->buffer = NULL;
@@ -62,7 +62,7 @@ archive_read_support_filter_grzip(struct archive *_a)
{ {
struct archive_read *a = (struct archive_read *)_a; struct archive_read *a = (struct archive_read *)_a;
if (__archive_read_register_bidder(a, NULL, NULL, if (__archive_read_register_bidder(a, NULL, "grzip",
&grzip_bidder_vtable) != ARCHIVE_OK) &grzip_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
@@ -363,7 +363,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p)
case READ_LEGACY_STREAM: case READ_LEGACY_STREAM:
/* Reading a lz4 stream already failed. */ /* Reading a lz4 stream already failed. */
archive_set_error(&self->archive->archive, archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC, "Invalid sequence."); ARCHIVE_ERRNO_MISC, "Invalid sequence");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
case READ_DEFAULT_BLOCK: case READ_DEFAULT_BLOCK:
ret = lz4_filter_read_default_stream(self, p); ret = lz4_filter_read_default_stream(self, p);
@@ -377,7 +377,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p)
break; break;
default: default:
archive_set_error(&self->archive->archive, archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC, "Program error."); ARCHIVE_ERRNO_MISC, "Program error");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -110,7 +110,7 @@ archive_read_support_filter_lzop(struct archive *_a)
{ {
struct archive_read *a = (struct archive_read *)_a; struct archive_read *a = (struct archive_read *)_a;
if (__archive_read_register_bidder(a, NULL, NULL, if (__archive_read_register_bidder(a, NULL, "lzop",
&lzop_bidder_vtable) != ARCHIVE_OK) &lzop_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
@@ -149,6 +149,8 @@ archive_read_support_filter_program_signature(struct archive *_a,
if (signature != NULL && signature_len > 0) { if (signature != NULL && signature_len > 0) {
state->signature_len = signature_len; state->signature_len = signature_len;
state->signature = malloc(signature_len); state->signature = malloc(signature_len);
if (state->signature == NULL)
goto memerr;
memcpy(state->signature, signature, signature_len); memcpy(state->signature, signature, signature_len);
} }
@@ -34,6 +34,9 @@
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
#include <stdlib.h> #include <stdlib.h>
#endif #endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_BZLIB_H #ifdef HAVE_BZLIB_H
#include <bzlib.h> #include <bzlib.h>
#endif #endif
@@ -80,7 +83,7 @@
/* /*
* ELF format * ELF format
*/ */
#define ELF_HDR_MIN_LEN 0x3f #define ELF_HDR_MIN_LEN 0x40 /* sizeof(Elf64_Ehdr) */
#define ELF_HDR_EI_CLASS_OFFSET 0x04 #define ELF_HDR_EI_CLASS_OFFSET 0x04
#define ELF_HDR_EI_DATA_OFFSET 0x05 #define ELF_HDR_EI_DATA_OFFSET 0x05
@@ -855,13 +858,18 @@ find_elf_data_sec(struct archive_read *a)
while (e_shnum > 0) { while (e_shnum > 0) {
name_offset = (*dec32)(h + sec_tbl_offset); name_offset = (*dec32)(h + sec_tbl_offset);
if (name_offset == data_sym_offset) { if (name_offset == data_sym_offset) {
uint64_t sel_offset;
if (format_64) { if (format_64) {
min_addr = (*dec64)( sel_offset = (*dec64)(
h + sec_tbl_offset + 0x18); h + sec_tbl_offset + 0x18);
} else { } else {
min_addr = (*dec32)( sel_offset = (*dec32)(
h + sec_tbl_offset + 0x10); h + sec_tbl_offset + 0x10);
} }
if (sel_offset > SSIZE_MAX)
break;
min_addr = (ssize_t)sel_offset;
break; break;
} }
sec_tbl_offset += e_shentsize; sec_tbl_offset += e_shentsize;
@@ -967,7 +975,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname cannot be converted " "Pathname cannot be converted "
"from %s to current locale.", "from %s to current locale",
archive_string_conversion_charset_name(zip->sconv)); archive_string_conversion_charset_name(zip->sconv));
ret = ARCHIVE_WARN; ret = ARCHIVE_WARN;
} }
@@ -1573,7 +1581,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
-15 /* Don't check for zlib header */); -15 /* Don't check for zlib header */);
if (r != Z_OK) { if (r != Z_OK) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Couldn't initialize zlib stream."); "Couldn't initialize zlib stream");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
zip->stream_valid = 1; zip->stream_valid = 1;
@@ -1715,7 +1723,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
if (bytes < 0) { if (bytes < 0) {
archive_set_error(&(a->archive), archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC, ARCHIVE_ERRNO_MISC,
"BCJ2 conversion Failed"); "BCJ2 conversion failed");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
zip->main_stream_bytes_remaining -= zip->main_stream_bytes_remaining -=
@@ -1971,7 +1979,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
bytes = Bcj2_Decode(zip, bcj2_next_out, bcj2_avail_out); bytes = Bcj2_Decode(zip, bcj2_next_out, bcj2_avail_out);
if (bytes < 0) { if (bytes < 0) {
archive_set_error(&(a->archive), archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC, "BCJ2 conversion Failed"); ARCHIVE_ERRNO_MISC, "BCJ2 conversion failed");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
zip->main_stream_bytes_remaining -= zip->main_stream_bytes_remaining -=
@@ -383,8 +383,10 @@ archive_read_support_format_cab(struct archive *_a)
NULL, NULL,
NULL); NULL);
if (r != ARCHIVE_OK) if (r != ARCHIVE_OK) {
archive_wstring_free(&cab->ws);
free(cab); free(cab);
}
return (ARCHIVE_OK); return (ARCHIVE_OK);
} }
@@ -978,7 +980,7 @@ archive_read_format_cab_read_header(struct archive_read *a,
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname cannot be converted " "Pathname cannot be converted "
"from %s to current locale.", "from %s to current locale",
archive_string_conversion_charset_name(sconv)); archive_string_conversion_charset_name(sconv));
err = ARCHIVE_WARN; err = ARCHIVE_WARN;
} }
@@ -1024,7 +1026,7 @@ archive_read_format_cab_read_data(struct archive_read *a,
*offset = 0; *offset = 0;
archive_clear_error(&a->archive); archive_clear_error(&a->archive);
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Cannot restore this file split in multivolume."); "Cannot restore this file split in multivolume");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
default: default:
break; break;
@@ -1173,6 +1175,9 @@ cab_checksum_finish(struct archive_read *a)
l = 4; l = 4;
if (cab->cfheader.flags & RESERVE_PRESENT) if (cab->cfheader.flags & RESERVE_PRESENT)
l += cab->cfheader.cfdata; l += cab->cfheader.cfdata;
if (cfdata->memimage == NULL) {
return (ARCHIVE_FAILED);
}
cfdata->sum_calculated = cab_checksum_cfdata( cfdata->sum_calculated = cab_checksum_cfdata(
cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated); cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated);
if (cfdata->sum_calculated != cfdata->sum) { if (cfdata->sum_calculated != cfdata->sum) {
@@ -1447,7 +1452,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
-15 /* Don't check for zlib header */); -15 /* Don't check for zlib header */);
if (r != Z_OK) { if (r != Z_OK) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't initialize deflate decompression."); "Can't initialize deflate decompression");
*avail = ARCHIVE_FATAL; *avail = ARCHIVE_FATAL;
return (NULL); return (NULL);
} }
@@ -1667,7 +1672,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
cab->entry_cffolder->compdata); cab->entry_cffolder->compdata);
if (r != ARCHIVE_OK) { if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't initialize LZX decompression."); "Can't initialize LZX decompression");
*avail = ARCHIVE_FATAL; *avail = ARCHIVE_FATAL;
return (NULL); return (NULL);
} }
@@ -1686,6 +1691,13 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
cab->xstrm.avail_out = cab->xstrm.avail_out =
cfdata->uncompressed_size - cab->xstrm.total_out; cfdata->uncompressed_size - cab->xstrm.total_out;
if ((size_t)cfdata->uncompressed_size > cab->uncompressed_buffer_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid CFDATA uncompressed size");
*avail = ARCHIVE_FATAL;
return (NULL);
}
d = __archive_read_ahead(a, 1, &bytes_avail); d = __archive_read_ahead(a, 1, &bytes_avail);
if (d == NULL) { if (d == NULL) {
archive_set_error(&a->archive, archive_set_error(&a->archive,
@@ -397,7 +397,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname can't be converted from %s to current locale.", "Pathname can't be converted from %s to current locale",
archive_string_conversion_charset_name(sconv)); archive_string_conversion_charset_name(sconv));
r = ARCHIVE_WARN; r = ARCHIVE_WARN;
} }
@@ -426,7 +426,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Linkname can't be converted from %s to " "Linkname can't be converted from %s to "
"current locale.", "current locale",
archive_string_conversion_charset_name(sconv)); archive_string_conversion_charset_name(sconv));
r = ARCHIVE_WARN; r = ARCHIVE_WARN;
} }
@@ -1322,7 +1322,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname cannot be converted " "Pathname cannot be converted "
"from %s to current locale.", "from %s to current locale",
archive_string_conversion_charset_name( archive_string_conversion_charset_name(
iso9660->sconv_utf16be)); iso9660->sconv_utf16be));
@@ -1400,7 +1400,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Linkname cannot be converted " "Linkname cannot be converted "
"from %s to current locale.", "from %s to current locale",
archive_string_conversion_charset_name( archive_string_conversion_charset_name(
iso9660->sconv_utf16be)); iso9660->sconv_utf16be));
rd_r = ARCHIVE_WARN; rd_r = ARCHIVE_WARN;
@@ -1663,7 +1663,7 @@ zisofs_read_data(struct archive_read *a,
r = inflateInit(&zisofs->stream); r = inflateInit(&zisofs->stream);
if (r != Z_OK) { if (r != Z_OK) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't initialize zisofs decompression."); "Can't initialize zisofs decompression");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
zisofs->stream_valid = 1; zisofs->stream_valid = 1;
@@ -1728,7 +1728,7 @@ zisofs_read_data(struct archive_read *a,
(void)size;/* UNUSED */ (void)size;/* UNUSED */
(void)offset;/* UNUSED */ (void)offset;/* UNUSED */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"zisofs is not supported on this platform."); "zisofs is not supported on this platform");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
@@ -2759,6 +2759,14 @@ parse_rockridge_ZF1(struct file_info *file, const unsigned char *data,
/* paged zlib */ /* paged zlib */
file->pz = 1; file->pz = 1;
file->pz_log2_bs = data[3]; file->pz_log2_bs = data[3];
if (file->pz_log2_bs < 15 || file->pz_log2_bs > 17) {
/* TODO: Return an error here instead of silently
* disabling zisofs. That requires propagating an
* error return through parse_rockridge() and its
* callers. */
file->pz = 0;
return;
}
file->pz_uncompressed_size = archive_le32dec(&data[4]); file->pz_uncompressed_size = archive_le32dec(&data[4]);
} }
} }
@@ -613,7 +613,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname cannot be converted " "Pathname cannot be converted "
"from %s to Unicode.", "from %s to Unicode",
archive_string_conversion_charset_name(lha->sconv_dir)); archive_string_conversion_charset_name(lha->sconv_dir));
err = ARCHIVE_FATAL; err = ARCHIVE_FATAL;
} else if (0 != archive_mstring_get_wcs(&a->archive, &conv_buffer, &conv_buffer_p)) } else if (0 != archive_mstring_get_wcs(&a->archive, &conv_buffer, &conv_buffer_p))
@@ -634,7 +634,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname cannot be converted " "Pathname cannot be converted "
"from %s to Unicode.", "from %s to Unicode",
archive_string_conversion_charset_name(lha->sconv_fname)); archive_string_conversion_charset_name(lha->sconv_fname));
err = ARCHIVE_FATAL; err = ARCHIVE_FATAL;
} }
@@ -1101,6 +1101,13 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha)
header_crc = lha_crc16(0, p, H3_FIXED_SIZE); header_crc = lha_crc16(0, p, H3_FIXED_SIZE);
__archive_read_consume(a, H3_FIXED_SIZE); __archive_read_consume(a, H3_FIXED_SIZE);
/* Reject rediculously large header */
if (lha->header_size > 65536) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"LHa header size too large");
return (ARCHIVE_FATAL);
}
/* Read extended headers */ /* Read extended headers */
err = lha_read_file_extended_header(a, lha, &header_crc, 4, err = lha_read_file_extended_header(a, lha, &header_crc, 4,
lha->header_size - H3_FIXED_SIZE, &extdsize); lha->header_size - H3_FIXED_SIZE, &extdsize);
@@ -301,6 +301,11 @@ cleanup(struct archive_read *a)
mtree = (struct mtree *)(a->format->data); mtree = (struct mtree *)(a->format->data);
/* Close any dangling file descriptor before freeing */
if (mtree->fd >= 0) {
close(mtree->fd);
mtree->fd = -1;
}
p = mtree->entries; p = mtree->entries;
while (p != NULL) { while (p != NULL) {
q = p->next; q = p->next;
@@ -955,7 +955,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) { if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Failed to read next header."); "Failed to read next header");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
p = h; p = h;
@@ -1005,7 +1005,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
archive_entry_set_is_data_encrypted(entry, 1); archive_entry_set_is_data_encrypted(entry, 1);
rar->has_encrypted_entries = 1; rar->has_encrypted_entries = 1;
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"RAR encryption support unavailable."); "RAR encryption support unavailable");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -1141,7 +1141,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
default: default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unsupported compression method for RAR file."); "Unsupported compression method for RAR file");
ret = ARCHIVE_FATAL; ret = ARCHIVE_FATAL;
break; break;
} }
@@ -1432,14 +1432,14 @@ read_header(struct archive_read *a, struct archive_entry *entry,
else else
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"RAR solid archive support unavailable."); "RAR solid archive support unavailable");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Failed to read full header content."); "Failed to read full header content");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -1471,7 +1471,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
archive_entry_set_is_data_encrypted(entry, 1); archive_entry_set_is_data_encrypted(entry, 1);
rar->has_encrypted_entries = 1; rar->has_encrypted_entries = 1;
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"RAR encryption support unavailable."); "RAR encryption support unavailable");
/* Since it is only the data part itself that is encrypted we can at least /* Since it is only the data part itself that is encrypted we can at least
extract information about the currently processed entry and don't need extract information about the currently processed entry and don't need
to return ARCHIVE_FATAL here. */ to return ARCHIVE_FATAL here. */
@@ -1503,7 +1503,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
if (rar->packed_size < 0 || rar->unp_size < 0) if (rar->packed_size < 0 || rar->unp_size < 0)
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid sizes specified."); "Invalid sizes specified");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -1516,19 +1516,19 @@ read_header(struct archive_read *a, struct archive_entry *entry,
size_t distance = p - (const char *)h; size_t distance = p - (const char *)h;
if (rar->packed_size > INT64_MAX - header_size) { if (rar->packed_size > INT64_MAX - header_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Extended header size too large."); "Extended header size too large");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
header_size += rar->packed_size; header_size += rar->packed_size;
if ((uintmax_t)header_size > SIZE_MAX) { if ((uintmax_t)header_size > SIZE_MAX) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unable to read extended header data."); "Unable to read extended header data");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
/* Make sure we have the extended data. */ /* Make sure we have the extended data. */
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) { if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Failed to read extended header data."); "Failed to read extended header data");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
p = h; p = h;
@@ -1547,7 +1547,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
newptr = realloc(rar->filename, newsize); newptr = realloc(rar->filename, newsize);
if (newptr == NULL) { if (newptr == NULL) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Couldn't allocate memory."); "Couldn't allocate memory");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
rar->filename = newptr; rar->filename = newptr;
@@ -1701,7 +1701,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
newsize = sizeof(*rar->dbo) * (rar->nodes + 1); newsize = sizeof(*rar->dbo) * (rar->nodes + 1);
if ((newdbo = realloc(rar->dbo, newsize)) == NULL) if ((newdbo = realloc(rar->dbo, newsize)) == NULL)
{ {
archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
rar->dbo = newdbo; rar->dbo = newdbo;
@@ -1715,7 +1715,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
if (rar->packed_size > INT64_MAX - a->filter->position) if (rar->packed_size > INT64_MAX - a->filter->position)
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unable to store offsets."); "Unable to store offsets");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
rar->dbo[rar->cursor].start_offset = a->filter->position; rar->dbo[rar->cursor].start_offset = a->filter->position;
@@ -1734,7 +1734,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
newsize = filename_size + 1; newsize = filename_size + 1;
if ((newptr = realloc(rar->filename_save, newsize)) == NULL) if ((newptr = realloc(rar->filename_save, newsize)) == NULL)
{ {
archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
rar->filename_save = newptr; rar->filename_save = newptr;
@@ -1745,7 +1745,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
free(rar->dbo); free(rar->dbo);
if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL) if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL)
{ {
archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
rar->dbo[0].header_size = header_size; rar->dbo[0].header_size = header_size;
@@ -1776,7 +1776,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
__archive_read_consume(a, header_size - 7); __archive_read_consume(a, header_size - 7);
if (rar->packed_size > INT64_MAX - a->filter->position) { if (rar->packed_size > INT64_MAX - a->filter->position) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unable to store offsets."); "Unable to store offsets");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
rar->dbo[0].start_offset = a->filter->position; rar->dbo[0].start_offset = a->filter->position;
@@ -1848,7 +1848,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname cannot be converted from %s to current locale.", "Pathname cannot be converted from %s to current locale",
archive_string_conversion_charset_name(fn_sconv)); archive_string_conversion_charset_name(fn_sconv));
ret = (ARCHIVE_WARN); ret = (ARCHIVE_WARN);
} }
@@ -1979,13 +1979,13 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
if ((uintmax_t)rar->packed_size > SIZE_MAX) if ((uintmax_t)rar->packed_size > SIZE_MAX)
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unable to read link."); "Unable to read link");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL) if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Failed to read link."); "Failed to read link");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
p = h; p = h;
@@ -2000,7 +2000,7 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"link cannot be converted from %s to current locale.", "link cannot be converted from %s to current locale",
archive_string_conversion_charset_name(sconv)); archive_string_conversion_charset_name(sconv));
ret = (ARCHIVE_WARN); ret = (ARCHIVE_WARN);
} }
@@ -2201,7 +2201,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
case 3: case 3:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Parsing filters is unsupported."); "Parsing filters is unsupported");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
case 4: case 4:
@@ -2473,7 +2473,7 @@ parse_codes(struct archive_read *a)
free(precode.tree); free(precode.tree);
free(precode.table); free(precode.table);
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Internal error extracting RAR file."); "Internal error extracting RAR file");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -2548,7 +2548,8 @@ parse_codes(struct archive_read *a)
return (r); return (r);
} }
if (!rar->dictionary_size || !rar->lzss.window) if (!rar->dictionary_size || !rar->lzss.window ||
(unsigned int)(rar->lzss.mask + 1) < rar->dictionary_size)
{ {
/* Seems as though dictionary sizes are not used. Even so, minimize /* Seems as though dictionary sizes are not used. Even so, minimize
* memory usage as much as possible. * memory usage as much as possible.
@@ -2562,13 +2563,13 @@ parse_codes(struct archive_read *a)
new_size = rar_fls((unsigned int)rar->unp_size) << 1; new_size = rar_fls((unsigned int)rar->unp_size) << 1;
if (new_size == 0) { if (new_size == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Zero window size is invalid."); "Zero window size is invalid");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
new_window = realloc(rar->lzss.window, new_size); new_window = realloc(rar->lzss.window, new_size);
if (new_window == NULL) { if (new_window == NULL) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Unable to allocate memory for uncompressed data."); "Unable to allocate memory for uncompressed data");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
rar->lzss.window = (unsigned char *)new_window; rar->lzss.window = (unsigned char *)new_window;
@@ -2686,7 +2687,7 @@ create_code(struct archive_read *a, struct huffman_code *code,
code->numallocatedentries = 0; code->numallocatedentries = 0;
if (new_node(code) < 0) { if (new_node(code) < 0) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Unable to allocate memory for node data."); "Unable to allocate memory for node data");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
code->numentries = 1; code->numentries = 1;
@@ -2769,12 +2770,12 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
if ((repeatnode = new_node(code)) < 0) { if ((repeatnode = new_node(code)) < 0) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Unable to allocate memory for node data."); "Unable to allocate memory for node data");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
if ((nextnode = new_node(code)) < 0) { if ((nextnode = new_node(code)) < 0) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Unable to allocate memory for node data."); "Unable to allocate memory for node data");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -2794,7 +2795,7 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
{ {
if (new_node(code) < 0) { if (new_node(code) < 0) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Unable to allocate memory for node data."); "Unable to allocate memory for node data");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
code->tree[lastnode].branches[bit] = code->numentries++; code->tree[lastnode].branches[bit] = code->numentries++;
@@ -2863,13 +2864,13 @@ make_table_recurse(struct archive_read *a, struct huffman_code *code, int node,
if (!code->tree) if (!code->tree)
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Huffman tree was not created."); "Huffman tree was not created");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
if (node < 0 || node >= code->numentries) if (node < 0 || node >= code->numentries)
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid location to Huffman tree specified."); "Invalid location to Huffman tree specified");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -3149,6 +3150,11 @@ copy_from_lzss_window(struct archive_read *a, uint8_t *buffer,
windowoffs = lzss_offset_for_position(&rar->lzss, startpos); windowoffs = lzss_offset_for_position(&rar->lzss, startpos);
firstpart = lzss_size(&rar->lzss) - windowoffs; firstpart = lzss_size(&rar->lzss) - windowoffs;
if (length > lzss_size(&rar->lzss)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Bad RAR file data");
return (ARCHIVE_FATAL);
}
if (firstpart < 0) { if (firstpart < 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Bad RAR file data"); "Bad RAR file data");
@@ -3180,7 +3186,7 @@ copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer,
if ((rar->unp_buffer = malloc(rar->unp_buffer_size)) == NULL) if ((rar->unp_buffer = malloc(rar->unp_buffer_size)) == NULL)
{ {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Unable to allocate memory for uncompressed data."); "Unable to allocate memory for uncompressed data");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
} }
@@ -3315,7 +3321,8 @@ parse_filter(struct archive_read *a, const uint8_t *bytes, uint16_t length, uint
else else
blocklength = prog ? prog->oldfilterlength : 0; blocklength = prog ? prog->oldfilterlength : 0;
if (blocklength > rar->dictionary_size) if (blocklength > rar->dictionary_size ||
blocklength > (uint32_t)(rar->lzss.mask + 1))
return 0; return 0;
registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS; registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS;
@@ -375,6 +375,7 @@ static int rar5_read_data_skip(struct archive_read *a);
static int push_data_ready(struct archive_read* a, struct rar5* rar, static int push_data_ready(struct archive_read* a, struct rar5* rar,
const uint8_t* buf, size_t size, int64_t offset); const uint8_t* buf, size_t size, int64_t offset);
static void clear_data_ready_stack(struct rar5* rar); static void clear_data_ready_stack(struct rar5* rar);
static void rar5_deinit(struct rar5* rar);
/* CDE_xxx = Circular Double Ended (Queue) return values. */ /* CDE_xxx = Circular Double Ended (Queue) return values. */
enum CDE_RETURN_VALUES { enum CDE_RETURN_VALUES {
@@ -429,8 +430,7 @@ static int cdeque_front(struct cdeque* d, void** value) {
return CDE_OUT_OF_BOUNDS; return CDE_OUT_OF_BOUNDS;
} }
/* Pushes a new element into the end of this circular deque object. If current /* Pushes a new element into the end of this circular deque object. */
* size will exceed capacity, the oldest element will be overwritten. */
static int cdeque_push_back(struct cdeque* d, void* item) { static int cdeque_push_back(struct cdeque* d, void* item) {
if(d == NULL) if(d == NULL)
return CDE_PARAM; return CDE_PARAM;
@@ -554,7 +554,11 @@ static struct filter_info* add_new_filter(struct rar5* rar) {
return NULL; return NULL;
} }
cdeque_push_back(&rar->cstate.filters, cdeque_filter(f)); if (CDE_OK != cdeque_push_back(&rar->cstate.filters, cdeque_filter(f))) {
free(f);
return NULL;
}
return f; return f;
} }
@@ -671,7 +675,7 @@ static int run_filter(struct archive_read* a, struct filter_info* flt) {
rar->cstate.filtered_buf = malloc(flt->block_length); rar->cstate.filtered_buf = malloc(flt->block_length);
if(!rar->cstate.filtered_buf) { if(!rar->cstate.filtered_buf) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for filter data."); "Can't allocate memory for filter data");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
@@ -1847,7 +1851,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
rar->cstate.window_buf == NULL) { rar->cstate.window_buf == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Declared solid file, but no window buffer " "Declared solid file, but no window buffer "
"initialized yet."); "initialized yet");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
@@ -1857,7 +1861,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
(rar->file.dir == 0 && window_size == 0)) (rar->file.dir == 0 && window_size == 0))
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Declared dictionary size is not supported."); "Declared dictionary size is not supported");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
@@ -1869,7 +1873,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Window size for this solid file doesn't match " "Window size for this solid file doesn't match "
"the window size used in previous solid file. "); "the window size used in previous solid file");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
} }
@@ -1895,7 +1899,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
if(!new_window_buf) { if(!new_window_buf) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Not enough memory when trying to realloc the window " "Not enough memory when trying to realloc the window "
"buffer."); "buffer");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
@@ -3040,7 +3044,9 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
if(block_length < 4 || if(block_length < 4 ||
block_length > 0x400000 || block_length > 0x400000 ||
filter_type > FILTER_ARM || filter_type > FILTER_ARM ||
!is_valid_filter_block_start(rar, block_start)) !is_valid_filter_block_start(rar, block_start) ||
(rar->cstate.window_size > 0 &&
(ssize_t)block_length > rar->cstate.window_size >> 1))
{ {
archive_set_error(&ar->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&ar->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid filter encountered"); "Invalid filter encountered");
@@ -3051,7 +3057,7 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
filt = add_new_filter(rar); filt = add_new_filter(rar);
if(filt == NULL) { if(filt == NULL) {
archive_set_error(&ar->archive, ENOMEM, archive_set_error(&ar->archive, ENOMEM,
"Can't allocate memory for a filter descriptor."); "Can't allocate memory for a filter descriptor");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
@@ -3500,7 +3506,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size,
rar->vol.push_buf = malloc(block_size + 8); rar->vol.push_buf = malloc(block_size + 8);
if(!rar->vol.push_buf) { if(!rar->vol.push_buf) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for a merge block buffer."); "Can't allocate memory for a merge block buffer");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
@@ -3533,7 +3539,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size,
if(partial_offset + cur_block_size > block_size) { if(partial_offset + cur_block_size > block_size) {
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_PROGRAMMER, ARCHIVE_ERRNO_PROGRAMMER,
"Consumed too much data when merging blocks."); "Consumed too much data when merging blocks");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
@@ -3802,7 +3808,7 @@ static int push_data_ready(struct archive_read* a, struct rar5* rar,
* as an internal error. */ * as an internal error. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Error: premature end of data_ready stack"); "Premature end of data_ready stack");
return ARCHIVE_FATAL; return ARCHIVE_FATAL;
} }
@@ -4328,7 +4334,7 @@ static int rar5_cleanup(struct archive_read *a) {
free(rar->vol.push_buf); free(rar->vol.push_buf);
free_filters(rar); free_filters(rar);
cdeque_free(&rar->cstate.filters); rar5_deinit(rar);
free(rar); free(rar);
a->format->data = NULL; a->format->data = NULL;
@@ -4353,6 +4359,7 @@ static int rar5_has_encrypted_entries(struct archive_read *_a) {
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
} }
/* Must match deallocations in rar5_deinit */
static int rar5_init(struct rar5* rar) { static int rar5_init(struct rar5* rar) {
memset(rar, 0, sizeof(struct rar5)); memset(rar, 0, sizeof(struct rar5));
@@ -4368,6 +4375,11 @@ static int rar5_init(struct rar5* rar) {
return ARCHIVE_OK; return ARCHIVE_OK;
} }
/* Must match allocations in rar5_init */
static void rar5_deinit(struct rar5* rar) {
cdeque_free(&rar->cstate.filters);
}
int archive_read_support_format_rar5(struct archive *_a) { int archive_read_support_format_rar5(struct archive *_a) {
struct archive_read* ar; struct archive_read* ar;
int ret; int ret;
@@ -4404,8 +4416,9 @@ int archive_read_support_format_rar5(struct archive *_a) {
rar5_has_encrypted_entries); rar5_has_encrypted_entries);
if(ret != ARCHIVE_OK) { if(ret != ARCHIVE_OK) {
(void) rar5_cleanup(ar); rar5_deinit(rar);
free(rar);
} }
return ret; return ARCHIVE_OK;
} }
@@ -1202,7 +1202,7 @@ set_conversion_failed_error(struct archive_read *a,
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"%s can't be converted from %s to current locale.", "%s can't be converted from %s to current locale",
name, archive_string_conversion_charset_name(sconv)); name, archive_string_conversion_charset_name(sconv));
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
} }
@@ -733,7 +733,7 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
} }
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Gname cannot be converted from %s to current locale.", "Gname cannot be converted from %s to current locale",
archive_string_conversion_charset_name(xar->sconv)); archive_string_conversion_charset_name(xar->sconv));
r = ARCHIVE_WARN; r = ARCHIVE_WARN;
} }
@@ -748,7 +748,7 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
} }
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Uname cannot be converted from %s to current locale.", "Uname cannot be converted from %s to current locale",
archive_string_conversion_charset_name(xar->sconv)); archive_string_conversion_charset_name(xar->sconv));
r = ARCHIVE_WARN; r = ARCHIVE_WARN;
} }
@@ -762,7 +762,7 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
} }
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname cannot be converted from %s to current locale.", "Pathname cannot be converted from %s to current locale",
archive_string_conversion_charset_name(xar->sconv)); archive_string_conversion_charset_name(xar->sconv));
r = ARCHIVE_WARN; r = ARCHIVE_WARN;
} }
@@ -778,7 +778,7 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
} }
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Linkname cannot be converted from %s to current locale.", "Linkname cannot be converted from %s to current locale",
archive_string_conversion_charset_name(xar->sconv)); archive_string_conversion_charset_name(xar->sconv));
r = ARCHIVE_WARN; r = ARCHIVE_WARN;
} }
@@ -1008,7 +1008,7 @@ move_reading_point(struct archive_read *a, uint64_t offset)
if (pos == ARCHIVE_FAILED) { if (pos == ARCHIVE_FAILED) {
archive_set_error(&(a->archive), archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC, ARCHIVE_ERRNO_MISC,
"Cannot seek."); "Cannot seek");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
xar->offset = pos; xar->offset = pos;
@@ -1476,7 +1476,7 @@ decompression_init(struct archive_read *a, enum enctype encoding)
r = inflateInit(&(xar->stream)); r = inflateInit(&(xar->stream));
if (r != Z_OK) { if (r != Z_OK) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Couldn't initialize zlib stream."); "Couldn't initialize zlib stream");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
xar->stream_valid = 1; xar->stream_valid = 1;
@@ -1008,7 +1008,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname cannot be converted " "Pathname cannot be converted "
"from %s to current locale.", "from %s to current locale",
archive_string_conversion_charset_name(sconv)); archive_string_conversion_charset_name(sconv));
ret = ARCHIVE_WARN; ret = ARCHIVE_WARN;
} }
@@ -1256,7 +1256,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Symlink cannot be converted " "Symlink cannot be converted "
"from %s to current locale.", "from %s to current locale",
archive_string_conversion_charset_name( archive_string_conversion_charset_name(
sconv)); sconv));
ret = ARCHIVE_WARN; ret = ARCHIVE_WARN;
@@ -1921,7 +1921,7 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff,
switch(lz_ret) { switch(lz_ret) {
case LZMA_DATA_ERROR: case LZMA_DATA_ERROR:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"xz data error (error %d)", (int) lz_ret); "xz data error (%d)", (int) lz_ret);
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
case LZMA_NO_CHECK: case LZMA_NO_CHECK:
@@ -1930,7 +1930,7 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff,
default: default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"xz unknown error %d", (int) lz_ret); "xz unknown error (%d)", (int) lz_ret);
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
case LZMA_STREAM_END: case LZMA_STREAM_END:
@@ -2018,7 +2018,7 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
switch(lz_ret) { switch(lz_ret) {
case LZMA_DATA_ERROR: case LZMA_DATA_ERROR:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"lzma data error (error %d)", (int) lz_ret); "lzma data error (%d)", (int) lz_ret);
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
/* This case is optional in lzma alone format. It can happen, /* This case is optional in lzma alone format. It can happen,
@@ -2041,7 +2041,7 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
default: default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"lzma unknown error %d", (int) lz_ret); "lzma unknown error (%d)", (int) lz_ret);
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -2527,7 +2527,7 @@ zip_deflate_init(struct archive_read *a, struct zip *zip)
-15 /* Don't check for zlib header */); -15 /* Don't check for zlib header */);
if (r != Z_OK) { if (r != Z_OK) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't initialize ZIP decompression."); "Can't initialize ZIP decompression");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
/* Stream structure has been set up. */ /* Stream structure has been set up. */
@@ -3193,7 +3193,7 @@ archive_read_format_zip_read_data(struct archive_read *a,
!= (zip->entry_uncompressed_bytes_read & UINT32_MAX)) { != (zip->entry_uncompressed_bytes_read & UINT32_MAX)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"ZIP uncompressed data is wrong size " "ZIP uncompressed data is wrong size "
"(read %jd, expected %jd)\n", "(read %jd, expected %jd)",
(intmax_t)zip->entry_uncompressed_bytes_read, (intmax_t)zip->entry_uncompressed_bytes_read,
(intmax_t)zip->entry->uncompressed_size); (intmax_t)zip->entry->uncompressed_size);
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
+12 -2
View File
@@ -772,7 +772,7 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
int r; int r;
defchar_used = 0; defchar_used = 0;
if (to_cp == CP_UTF8 || sc == NULL) if (to_cp == CP_UTF8)
dp = NULL; dp = NULL;
else else
dp = &defchar_used; dp = &defchar_used;
@@ -1873,6 +1873,9 @@ archive_string_conversion_free(struct archive *a)
const char * const char *
archive_string_conversion_charset_name(struct archive_string_conv *sc) archive_string_conversion_charset_name(struct archive_string_conv *sc)
{ {
if (sc == NULL) {
return "current locale";
}
if (sc->flag & SCONV_TO_CHARSET) if (sc->flag & SCONV_TO_CHARSET)
return (sc->to_charset); return (sc->to_charset);
else else
@@ -4123,7 +4126,12 @@ archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes,
* character-set. */ * character-set. */
if ((aes->aes_set & AES_SET_MBS) == 0) { if ((aes->aes_set & AES_SET_MBS) == 0) {
const char *pm; /* unused */ const char *pm; /* unused */
archive_mstring_get_mbs(a, aes, &pm); /* ignore errors, we'll handle it later */ if (archive_mstring_get_mbs(a, aes, &pm) != 0) {
/* We have another form, but failed to convert it to
* the native locale. Transitively, we've failed to
* convert it to the specified character set. */
ret = -1;
}
} }
/* If we already have an MBS form, use it to be translated to /* If we already have an MBS form, use it to be translated to
* specified character-set. */ * specified character-set. */
@@ -4141,6 +4149,8 @@ archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes,
if (length != NULL) if (length != NULL)
*length = aes->aes_mbs_in_locale.length; *length = aes->aes_mbs_in_locale.length;
} else { } else {
/* Either we have no string in any form,
* or conversion failed and set 'ret != 0'. */
*p = NULL; *p = NULL;
if (length != NULL) if (length != NULL)
*length = 0; *length = 0;
@@ -742,7 +742,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
if (a->format_write_header == NULL) { if (a->format_write_header == NULL) {
archive_set_error(&(a->archive), -1, archive_set_error(&(a->archive), -1,
"Format must be set before you can write to an archive."); "Format must be set before you can write to an archive");
a->archive.state = ARCHIVE_STATE_FATAL; a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -28,6 +28,9 @@
#ifdef HAVE_ERRNO_H #ifdef HAVE_ERRNO_H
#include <errno.h> #include <errno.h>
#endif #endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
#include <stdlib.h> #include <stdlib.h>
#endif #endif
@@ -116,12 +119,20 @@ archive_filter_b64encode_options(struct archive_write_filter *f, const char *key
struct private_b64encode *state = (struct private_b64encode *)f->data; struct private_b64encode *state = (struct private_b64encode *)f->data;
if (strcmp(key, "mode") == 0) { if (strcmp(key, "mode") == 0) {
int64_t val;
if (value == NULL) { if (value == NULL) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"mode option requires octal digits"); "mode option requires octal digits");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
state->mode = (int)atol8(value, strlen(value)) & 0777; val = atol8(value, strlen(value));
if (val < 0 || val > INT_MAX) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"invalid mode option");
return (ARCHIVE_FAILED);
}
state->mode = (int)val & 0777;
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "name") == 0) { } else if (strcmp(key, "name") == 0) {
if (value == NULL) { if (value == NULL) {
@@ -287,13 +298,18 @@ atol8(const char *p, size_t char_cnt)
int64_t l; int64_t l;
int digit; int digit;
if (char_cnt == 0)
return (-1);
l = 0; l = 0;
while (char_cnt-- > 0) { while (char_cnt-- > 0) {
if (*p >= '0' && *p <= '7') if (*p >= '0' && *p <= '7')
digit = *p - '0'; digit = *p - '0';
else else
break; return (-1);
p++; p++;
if (l > (INT64_MAX >> 3))
return (-1);
l <<= 3; l <<= 3;
l |= digit; l |= digit;
} }
@@ -127,8 +127,11 @@ archive_compressor_bzip2_options(struct archive_write_filter *f,
if (strcmp(key, "compression-level") == 0) { if (strcmp(key, "compression-level") == 0) {
if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
value[1] != '\0') value[1] != '\0') {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"compression-level invalid");
return (ARCHIVE_FAILED);
}
data->compression_level = value[0] - '0'; data->compression_level = value[0] - '0';
/* Make '0' be a synonym for '1'. */ /* Make '0' be a synonym for '1'. */
/* This way, bzip2 compressor supports the same 0..9 /* This way, bzip2 compressor supports the same 0..9
@@ -160,8 +160,11 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
if (strcmp(key, "compression-level") == 0) { if (strcmp(key, "compression-level") == 0) {
if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
value[1] != '\0') value[1] != '\0') {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"compression-level invalid");
return (ARCHIVE_FAILED);
}
data->compression_level = value[0] - '0'; data->compression_level = value[0] - '0';
return (ARCHIVE_OK); return (ARCHIVE_OK);
} }
@@ -172,8 +175,11 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
if (strcmp(key, "original-filename") == 0) { if (strcmp(key, "original-filename") == 0) {
free((void*)data->original_filename); free((void*)data->original_filename);
data->original_filename = NULL; data->original_filename = NULL;
if (value) if (value) {
data->original_filename = strdup(value); data->original_filename = strdup(value);
if (data->original_filename == NULL)
return (ARCHIVE_WARN);
}
return (ARCHIVE_OK); return (ARCHIVE_OK);
} }
@@ -97,8 +97,11 @@ archive_write_lrzip_options(struct archive_write_filter *f, const char *key,
struct write_lrzip *data = (struct write_lrzip *)f->data; struct write_lrzip *data = (struct write_lrzip *)f->data;
if (strcmp(key, "compression") == 0) { if (strcmp(key, "compression") == 0) {
if (value == NULL) if (value == NULL) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"compression option requires an argument");
return (ARCHIVE_FAILED);
}
else if (strcmp(value, "bzip2") == 0) else if (strcmp(value, "bzip2") == 0)
data->compression = bzip2; data->compression = bzip2;
else if (strcmp(value, "gzip") == 0) else if (strcmp(value, "gzip") == 0)
@@ -109,13 +112,19 @@ archive_write_lrzip_options(struct archive_write_filter *f, const char *key,
data->compression = none; data->compression = none;
else if (strcmp(value, "zpaq") == 0) else if (strcmp(value, "zpaq") == 0)
data->compression = zpaq; data->compression = zpaq;
else else {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"compression invalid");
return (ARCHIVE_FAILED);
}
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "compression-level") == 0) { } else if (strcmp(key, "compression-level") == 0) {
if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
value[1] != '\0') value[1] != '\0') {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"compression-level invalid");
return (ARCHIVE_FAILED);
}
data->compression_level = value[0] - '0'; data->compression_level = value[0] - '0';
return (ARCHIVE_OK); return (ARCHIVE_OK);
} }
@@ -160,8 +160,11 @@ archive_filter_lz4_options(struct archive_write_filter *f,
if (strcmp(key, "compression-level") == 0) { if (strcmp(key, "compression-level") == 0) {
int val; int val;
if (value == NULL || !((val = value[0] - '0') >= 1 && val <= 9) || if (value == NULL || !((val = value[0] - '0') >= 1 && val <= 9) ||
value[1] != '\0') value[1] != '\0') {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"compression-level invalid");
return (ARCHIVE_FAILED);
}
#ifndef HAVE_LZ4HC_H #ifndef HAVE_LZ4HC_H
if(val >= 3) if(val >= 3)
@@ -184,8 +187,11 @@ archive_filter_lz4_options(struct archive_write_filter *f,
} }
if (strcmp(key, "block-size") == 0) { if (strcmp(key, "block-size") == 0) {
if (value == NULL || !(value[0] >= '4' && value[0] <= '7') || if (value == NULL || !(value[0] >= '4' && value[0] <= '7') ||
value[1] != '\0') value[1] != '\0') {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"block-size invalid");
return (ARCHIVE_FAILED);
}
data->block_maximum_size = value[0] - '0'; data->block_maximum_size = value[0] - '0';
return (ARCHIVE_OK); return (ARCHIVE_OK);
} }
@@ -211,8 +211,11 @@ archive_write_lzop_options(struct archive_write_filter *f, const char *key,
if (strcmp(key, "compression-level") == 0) { if (strcmp(key, "compression-level") == 0) {
if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
value[1] != '\0') value[1] != '\0') {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"compression-level invalid");
return (ARCHIVE_FAILED);
}
data->compression_level = value[0] - '0'; data->compression_level = value[0] - '0';
return (ARCHIVE_OK); return (ARCHIVE_OK);
} }
@@ -28,6 +28,9 @@
#ifdef HAVE_ERRNO_H #ifdef HAVE_ERRNO_H
#include <errno.h> #include <errno.h>
#endif #endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
#include <stdlib.h> #include <stdlib.h>
#endif #endif
@@ -105,12 +108,20 @@ archive_filter_uuencode_options(struct archive_write_filter *f, const char *key,
struct private_uuencode *state = (struct private_uuencode *)f->data; struct private_uuencode *state = (struct private_uuencode *)f->data;
if (strcmp(key, "mode") == 0) { if (strcmp(key, "mode") == 0) {
int64_t val;
if (value == NULL) { if (value == NULL) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"mode option requires octal digits"); "mode option requires octal digits");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
state->mode = (int)atol8(value, strlen(value)) & 0777; val = atol8(value, strlen(value));
if (val < 0 || val > INT_MAX) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"invalid mode option");
return (ARCHIVE_FAILED);
}
state->mode = (int)val & 0777;
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "name") == 0) { } else if (strcmp(key, "name") == 0) {
if (value == NULL) { if (value == NULL) {
@@ -278,13 +289,18 @@ atol8(const char *p, size_t char_cnt)
int64_t l; int64_t l;
int digit; int digit;
if (char_cnt == 0)
return (-1);
l = 0; l = 0;
while (char_cnt-- > 0) { while (char_cnt-- > 0) {
if (*p >= '0' && *p <= '7') if (*p >= '0' && *p <= '7')
digit = *p - '0'; digit = *p - '0';
else else
break; return (-1);
p++; p++;
if (l > (INT64_MAX >> 3))
return (-1);
l <<= 3; l <<= 3;
l |= digit; l |= digit;
} }
@@ -29,6 +29,9 @@
#ifdef HAVE_ERRNO_H #ifdef HAVE_ERRNO_H
#include <errno.h> #include <errno.h>
#endif #endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
#include <stdlib.h> #include <stdlib.h>
#endif #endif
@@ -376,23 +379,33 @@ archive_compressor_xz_options(struct archive_write_filter *f,
if (strcmp(key, "compression-level") == 0) { if (strcmp(key, "compression-level") == 0) {
if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
value[1] != '\0') value[1] != '\0') {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"compression-level invalid");
return (ARCHIVE_FAILED);
}
data->compression_level = value[0] - '0'; data->compression_level = value[0] - '0';
if (data->compression_level > 9) if (data->compression_level > 9)
data->compression_level = 9; data->compression_level = 9;
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "threads") == 0) { } else if (strcmp(key, "threads") == 0) {
char *endptr; char *endptr;
unsigned long val;
if (value == NULL) if (value == NULL) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
errno = 0; "threads option requires an argument");
data->threads = (int)strtoul(value, &endptr, 10); return (ARCHIVE_FAILED);
if (errno != 0 || *endptr != '\0') {
data->threads = 1;
return (ARCHIVE_WARN);
} }
errno = 0;
val = strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0' || val > (unsigned)INT_MAX) {
data->threads = 1;
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"threads invalid");
return (ARCHIVE_FAILED);
}
data->threads = (int)val;
if (data->threads == 0) { if (data->threads == 0) {
#ifdef HAVE_LZMA_STREAM_ENCODER_MT #ifdef HAVE_LZMA_STREAM_ENCODER_MT
data->threads = lzma_cputhreads(); data->threads = lzma_cputhreads();
@@ -245,7 +245,9 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
if (strcmp(key, "compression-level") == 0) { if (strcmp(key, "compression-level") == 0) {
intmax_t level; intmax_t level;
if (string_to_number(value, &level) != ARCHIVE_OK) { if (string_to_number(value, &level) != ARCHIVE_OK) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"compression-level invalid");
return (ARCHIVE_FAILED);
} }
/* If we don't have the library, hard-code the max level */ /* If we don't have the library, hard-code the max level */
int minimum = CLEVEL_MIN; int minimum = CLEVEL_MIN;
@@ -263,14 +265,18 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
} }
#endif #endif
if (level < minimum || level > maximum) { if (level < minimum || level > maximum) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"compression-level out of range");
return (ARCHIVE_FAILED);
} }
data->compression_level = (int)level; data->compression_level = (int)level;
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "threads") == 0) { } else if (strcmp(key, "threads") == 0) {
intmax_t threads; intmax_t threads;
if (string_to_number(value, &threads) != ARCHIVE_OK) { if (string_to_number(value, &threads) != ARCHIVE_OK) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"threads invalid");
return (ARCHIVE_FAILED);
} }
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
@@ -286,7 +292,9 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
} }
#endif #endif
if (threads < 0 || threads > INT_MAX) { if (threads < 0 || threads > INT_MAX) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"threads out of rnage");
return (ARCHIVE_FAILED);
} }
data->threads = (int)threads; data->threads = (int)threads;
return (ARCHIVE_OK); return (ARCHIVE_OK);
@@ -296,26 +304,34 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "min-frame-in") == 0) { } else if (strcmp(key, "min-frame-in") == 0) {
if (string_to_size(value, &data->min_frame_in) != ARCHIVE_OK) { if (string_to_size(value, &data->min_frame_in) != ARCHIVE_OK) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"min-frame-in invalid");
return (ARCHIVE_FAILED);
} }
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "min-frame-out") == 0 || } else if (strcmp(key, "min-frame-out") == 0 ||
strcmp(key, "min-frame-size") == 0) { strcmp(key, "min-frame-size") == 0) {
if (string_to_size(value, &data->min_frame_out) != ARCHIVE_OK) { if (string_to_size(value, &data->min_frame_out) != ARCHIVE_OK) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"min-frame-out invalid");
return (ARCHIVE_FAILED);
} }
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "max-frame-in") == 0 || } else if (strcmp(key, "max-frame-in") == 0 ||
strcmp(key, "max-frame-size") == 0) { strcmp(key, "max-frame-size") == 0) {
if (string_to_size(value, &data->max_frame_in) != ARCHIVE_OK || if (string_to_size(value, &data->max_frame_in) != ARCHIVE_OK ||
data->max_frame_in < 1024) { data->max_frame_in < 1024) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"max-frame-size invalid");
return (ARCHIVE_FAILED);
} }
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "max-frame-out") == 0) { } else if (strcmp(key, "max-frame-out") == 0) {
if (string_to_size(value, &data->max_frame_out) != ARCHIVE_OK || if (string_to_size(value, &data->max_frame_out) != ARCHIVE_OK ||
data->max_frame_out < 1024) { data->max_frame_out < 1024) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"max-frame-out invalid");
return (ARCHIVE_FAILED);
} }
return (ARCHIVE_OK); return (ARCHIVE_OK);
#endif #endif
@@ -323,22 +339,30 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
else if (strcmp(key, "long") == 0) { else if (strcmp(key, "long") == 0) {
intmax_t long_distance; intmax_t long_distance;
if (string_to_number(value, &long_distance) != ARCHIVE_OK) { if (string_to_number(value, &long_distance) != ARCHIVE_OK) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"long invalid");
return (ARCHIVE_FAILED);
} }
#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream && ZSTD_VERSION_NUMBER >= MINVER_LONG #if HAVE_ZSTD_H && HAVE_ZSTD_compressStream && ZSTD_VERSION_NUMBER >= MINVER_LONG
ZSTD_bounds bounds = ZSTD_cParam_getBounds(ZSTD_c_windowLog); ZSTD_bounds bounds = ZSTD_cParam_getBounds(ZSTD_c_windowLog);
if (ZSTD_isError(bounds.error)) { if (ZSTD_isError(bounds.error)) {
int max_distance = ((int)(sizeof(size_t) == 4 ? 30 : 31)); int max_distance = ((int)(sizeof(size_t) == 4 ? 30 : 31));
if (((int)long_distance) < 10 || (int)long_distance > max_distance) if (((int)long_distance) < 10 || (int)long_distance > max_distance) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"long out of range");
return (ARCHIVE_FAILED);
}
} else { } else {
if ((int)long_distance < bounds.lowerBound || (int)long_distance > bounds.upperBound) if ((int)long_distance < bounds.lowerBound || (int)long_distance > bounds.upperBound) {
return (ARCHIVE_WARN); archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"long out of range");
return (ARCHIVE_FAILED);
}
} }
#else #else
int max_distance = ((int)(sizeof(size_t) == 4 ? 30 : 31)); int max_distance = ((int)(sizeof(size_t) == 4 ? 30 : 31));
if (((int)long_distance) < 10 || (int)long_distance > max_distance) if (((int)long_distance) < 10 || (int)long_distance > max_distance)
return (ARCHIVE_WARN); return (ARCHIVE_FAILED);
#endif #endif
data->long_distance = (int)long_distance; data->long_distance = (int)long_distance;
return (ARCHIVE_OK); return (ARCHIVE_OK);
@@ -2119,7 +2119,7 @@ restore_entry(struct archive_write_disk *a)
if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) { if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) {
archive_set_error(&a->archive, en, archive_set_error(&a->archive, en,
"Hard-link target '%s' does not exist.", "Hard-link target '%s' does not exist",
archive_entry_hardlink(a->entry)); archive_entry_hardlink(a->entry));
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
@@ -3447,8 +3447,17 @@ create_dir(struct archive_write_disk *a, char *path)
* don't add it to the fixup list here, as it's already been * don't add it to the fixup list here, as it's already been
* added. * added.
*/ */
if (la_stat(path, &st) == 0 && S_ISDIR(st.st_mode)) if (errno == EEXIST) {
if (la_stat(path, &st) == 0) {
if (S_ISDIR(st.st_mode))
return (ARCHIVE_OK); return (ARCHIVE_OK);
/* path exists but is not a directory */
errno = ENOTDIR;
} else {
/* restore original errno */
errno = EEXIST;
}
}
archive_set_error(&a->archive, errno, "Failed to create dir '%s'", archive_set_error(&a->archive, errno, "Failed to create dir '%s'",
path); path);
@@ -4010,7 +4019,7 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
#elif defined(HAVE_CHFLAGS) #elif defined(HAVE_CHFLAGS)
if (S_ISLNK(a->st.st_mode)) { if (S_ISLNK(a->st.st_mode)) {
archive_set_error(&a->archive, errno, archive_set_error(&a->archive, errno,
"Can't set file flags on symlink."); "Can't set file flags on symlink");
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
} }
if (chflags(name, a->st.st_flags) == 0) if (chflags(name, a->st.st_flags) == 0)
@@ -4569,7 +4578,7 @@ set_xattrs(struct archive_write_disk *a)
} else } else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore extended " "Cannot restore extended "
"attributes on this file system."); "attributes on this file system");
} }
archive_string_free(&errlist); archive_string_free(&errlist);
@@ -4671,7 +4680,7 @@ set_xattrs(struct archive_write_disk *a)
} else } else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore extended " "Cannot restore extended "
"attributes on this file system."); "attributes on this file system");
} }
archive_string_free(&errlist); archive_string_free(&errlist);
@@ -4767,4 +4776,3 @@ static void close_file_descriptor(struct archive_write_disk* a)
#endif /* !_WIN32 || __CYGWIN__ */ #endif /* !_WIN32 || __CYGWIN__ */
@@ -28,6 +28,9 @@
#ifdef HAVE_ERRNO_H #ifdef HAVE_ERRNO_H
#include <errno.h> #include <errno.h>
#endif #endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
#include <stdlib.h> #include <stdlib.h>
#endif #endif
@@ -333,6 +336,7 @@ string_to_number(const char *string, intmax_t *numberp)
if (string == NULL || *string == '\0') if (string == NULL || *string == '\0')
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
errno = 0;
*numberp = strtoimax(string, &end, 10); *numberp = strtoimax(string, &end, 10);
if (end == string || *end != '\0' || errno == EOVERFLOW) { if (end == string || *end != '\0' || errno == EOVERFLOW) {
*numberp = 0; *numberp = 0;
@@ -487,8 +491,9 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
} }
char *end = NULL; char *end = NULL;
errno = 0;
long lvl = strtol(value, &end, 10); long lvl = strtol(value, &end, 10);
if (end == NULL || *end != '\0') { if (errno != 0 || end == NULL || *end != '\0') {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"parsing compression-level option value failed `%s'", value); "parsing compression-level option value failed `%s'", value);
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
@@ -525,7 +530,7 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
if (string_to_number(value, &threads) != ARCHIVE_OK) { if (string_to_number(value, &threads) != ARCHIVE_OK) {
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
} }
if (threads < 0) { if (threads < 0 || threads > INT_MAX) {
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
} }
if (threads == 0) { if (threads == 0) {
@@ -506,12 +506,12 @@ write_header(struct archive_write *a, struct archive_entry *entry)
if ((a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) && if ((a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) &&
(archive_entry_size(entry) > 256*256*256-1)) { (archive_entry_size(entry) > 256*256*256-1)) {
archive_set_error(&a->archive, ERANGE, archive_set_error(&a->archive, ERANGE,
"File is too large for PWB binary cpio format."); "File is too large for PWB binary cpio format");
ret_final = ARCHIVE_FAILED; ret_final = ARCHIVE_FAILED;
goto exit_write_header; goto exit_write_header;
} else if (archive_entry_size(entry) > INT32_MAX) { } else if (archive_entry_size(entry) > INT32_MAX) {
archive_set_error(&a->archive, ERANGE, archive_set_error(&a->archive, ERANGE,
"File is too large for binary cpio format."); "File is too large for binary cpio format");
ret_final = ARCHIVE_FAILED; ret_final = ARCHIVE_FAILED;
goto exit_write_header; goto exit_write_header;
} }
@@ -322,7 +322,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
h + c_filesize_offset, c_filesize_size); h + c_filesize_offset, c_filesize_size);
if (ret) { if (ret) {
archive_set_error(&a->archive, ERANGE, archive_set_error(&a->archive, ERANGE,
"File is too large for this format."); "File is too large for this format");
ret_final = ARCHIVE_FAILED; ret_final = ARCHIVE_FAILED;
goto exit_write_header; goto exit_write_header;
} }
@@ -380,7 +380,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
h + c_filesize_offset, c_filesize_size); h + c_filesize_offset, c_filesize_size);
if (ret) { if (ret) {
archive_set_error(&a->archive, ERANGE, archive_set_error(&a->archive, ERANGE,
"File is too large for cpio format."); "File is too large for cpio format");
ret_final = ARCHIVE_FAILED; ret_final = ARCHIVE_FAILED;
goto exit_write_header; goto exit_write_header;
} }
@@ -293,6 +293,17 @@ archive_write_gnutar_header(struct archive_write *a,
} else } else
sconv = gnutar->opt_sconv; sconv = gnutar->opt_sconv;
/* Sanity check. */
if (archive_entry_pathname(entry) == NULL
#if defined(_WIN32) && !defined(__CYGWIN__)
&& archive_entry_pathname_w(entry) == NULL
#endif
) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't record entry in tar file without pathname");
return ARCHIVE_FAILED;
}
/* Only regular files (not hardlinks) have data. */ /* Only regular files (not hardlinks) have data. */
if (archive_entry_hardlink(entry) != NULL || if (archive_entry_hardlink(entry) != NULL ||
archive_entry_symlink(entry) != NULL || archive_entry_symlink(entry) != NULL ||
@@ -385,17 +396,30 @@ archive_write_gnutar_header(struct archive_write *a,
r = archive_entry_pathname_l(entry, &(gnutar->pathname), r = archive_entry_pathname_l(entry, &(gnutar->pathname),
&(gnutar->pathname_length), sconv); &(gnutar->pathname_length), sconv);
if (r != 0) { if (r != 0) {
const char* p_mbs;
if (errno == ENOMEM) { if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for pathname"); "Can't allocate memory for pathname");
ret = ARCHIVE_FATAL; ret = ARCHIVE_FATAL;
goto exit_write_header; goto exit_write_header;
} }
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, p_mbs = archive_entry_pathname(entry);
"Can't translate pathname '%s' to %s", if (p_mbs) {
archive_entry_pathname(entry), /* We have a wrongly-encoded MBS pathname.
* Warn and use it. */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname '%s' to %s", p_mbs,
archive_string_conversion_charset_name(sconv)); archive_string_conversion_charset_name(sconv));
ret2 = ARCHIVE_WARN; ret2 = ARCHIVE_WARN;
} else {
/* We have no MBS pathname. Fail. */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname to %s",
archive_string_conversion_charset_name(sconv));
return ARCHIVE_FAILED;
}
} }
r = archive_entry_uname_l(entry, &(gnutar->uname), r = archive_entry_uname_l(entry, &(gnutar->uname),
&(gnutar->uname_length), sconv); &(gnutar->uname_length), sconv);
@@ -1381,7 +1381,7 @@ iso9660_options(struct archive_write *a, const char *key, const char *value)
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC, ARCHIVE_ERRNO_MISC,
"Option ``%s'' " "Option ``%s'' "
"is not supported on this platform.", key); "is not supported on this platform", key);
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
#endif #endif
} }
@@ -1503,7 +1503,7 @@ iso9660_options(struct archive_write *a, const char *key, const char *value)
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC, ARCHIVE_ERRNO_MISC,
"``zisofs'' " "``zisofs'' "
"is not supported on this platform."); "is not supported on this platform");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
#endif #endif
} }
@@ -1539,7 +1539,7 @@ iso9660_write_header(struct archive_write *a, struct archive_entry *entry)
if (archive_entry_filetype(entry) == AE_IFLNK if (archive_entry_filetype(entry) == AE_IFLNK
&& iso9660->opt.rr == OPT_RR_DISABLED) { && iso9660->opt.rr == OPT_RR_DISABLED) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Ignore symlink file."); "Ignore symlink file");
iso9660->cur_file = NULL; iso9660->cur_file = NULL;
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
} }
@@ -1549,7 +1549,7 @@ iso9660_write_header(struct archive_write *a, struct archive_entry *entry)
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC, ARCHIVE_ERRNO_MISC,
"Ignore over %lld bytes file. " "Ignore over %lld bytes file. "
"This file too large.", "This file too large",
MULTI_EXTENT_SIZE); MULTI_EXTENT_SIZE);
iso9660->cur_file = NULL; iso9660->cur_file = NULL;
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
@@ -2103,7 +2103,7 @@ iso9660_close(struct archive_write *a)
if (iso9660->directories_too_deep != NULL) { if (iso9660->directories_too_deep != NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"%s: Directories too deep.", "%s: Directories too deep",
archive_entry_pathname( archive_entry_pathname(
iso9660->directories_too_deep->file->entry)); iso9660->directories_too_deep->file->entry));
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
@@ -3799,7 +3799,7 @@ set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc,
isoent = isoent_find_entry(vdd->rootent, ids); isoent = isoent_find_entry(vdd->rootent, ids);
if (isoent == NULL) { if (isoent == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Not Found %s `%s'.", "Not Found %s `%s'",
label, ids); label, ids);
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -7080,7 +7080,7 @@ isoent_make_path_table(struct archive_write *a)
* See also ISO9660 Standard 9.4. * See also ISO9660 Standard 9.4.
*/ */
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Too many directories(%d) over 65535.", dir_number); "Too many directories(%d) over 65535", dir_number);
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -7203,7 +7203,7 @@ isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
else { else {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Boot image file(``%s'') size is too big " "Boot image file(``%s'') size is too big "
"for fd type.", "for fd type",
iso9660->el_torito.boot_filename.s); iso9660->el_torito.boot_filename.s);
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@@ -7964,7 +7964,7 @@ zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs,
r = inflateInit(&zisofs->stream); r = inflateInit(&zisofs->stream);
if (r != Z_OK) { if (r != Z_OK) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't initialize zisofs decompression."); "Can't initialize zisofs decompression");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
zisofs->stream_valid = 1; zisofs->stream_valid = 1;
@@ -2262,7 +2262,7 @@ mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np,
if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) { if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Found duplicate entries for `%s' with " "Found duplicate entries for `%s' with "
"differing file types.", "differing file types",
np->pathname.s); np->pathname.s);
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
@@ -1062,7 +1062,7 @@ archive_write_pax_header(struct archive_write *a,
} }
/* If numeric GID is too large, add 'gid' to pax extended attrs. */ /* If numeric GID is too large, add 'gid' to pax extended attrs. */
if ((unsigned int)archive_entry_gid(entry_main) >= (1 << 18)) { if (archive_entry_gid(entry_main) >= (1 << 18)) {
add_pax_attr_int(&(pax->pax_header), "gid", add_pax_attr_int(&(pax->pax_header), "gid",
archive_entry_gid(entry_main)); archive_entry_gid(entry_main));
need_extension = 1; need_extension = 1;
@@ -1078,7 +1078,7 @@ archive_write_pax_header(struct archive_write *a,
} }
/* If numeric UID is too large, add 'uid' to pax extended attrs. */ /* If numeric UID is too large, add 'uid' to pax extended attrs. */
if ((unsigned int)archive_entry_uid(entry_main) >= (1 << 18)) { if (archive_entry_uid(entry_main) >= (1 << 18)) {
add_pax_attr_int(&(pax->pax_header), "uid", add_pax_attr_int(&(pax->pax_header), "uid",
archive_entry_uid(entry_main)); archive_entry_uid(entry_main));
need_extension = 1; need_extension = 1;
@@ -1471,7 +1471,7 @@ archive_write_pax_header(struct archive_write *a,
if (r < ARCHIVE_WARN) { if (r < ARCHIVE_WARN) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"archive_write_pax_header: " "archive_write_pax_header: "
"'x' header failed?! This can't happen.\n"); "'x' header failed?! This can't happen");
archive_entry_free(entry_main); archive_entry_free(entry_main);
archive_string_free(&entry_name); archive_string_free(&entry_name);
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
@@ -254,11 +254,11 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
sconv = ustar->opt_sconv; sconv = ustar->opt_sconv;
/* Sanity check. */ /* Sanity check. */
if (archive_entry_pathname(entry) == NULL
#if defined(_WIN32) && !defined(__CYGWIN__) #if defined(_WIN32) && !defined(__CYGWIN__)
if (archive_entry_pathname_w(entry) == NULL) { && archive_entry_pathname_w(entry) == NULL
#else
if (archive_entry_pathname(entry) == NULL) {
#endif #endif
) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't record entry in tar file without pathname"); "Can't record entry in tar file without pathname");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
@@ -409,15 +409,28 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
*/ */
r = archive_entry_pathname_l(entry, &pp, &copy_length, sconv); r = archive_entry_pathname_l(entry, &pp, &copy_length, sconv);
if (r != 0) { if (r != 0) {
const char* p_mbs;
if (errno == ENOMEM) { if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Pathname"); "Can't allocate memory for Pathname");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
p_mbs = archive_entry_pathname(entry);
if (p_mbs) {
/* We have a wrongly-encoded MBS pathname.
* Warn and use it. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname '%s' to %s", "Can't translate pathname '%s' to %s", p_mbs,
pp, archive_string_conversion_charset_name(sconv)); archive_string_conversion_charset_name(sconv));
ret = ARCHIVE_WARN; ret = ARCHIVE_WARN;
} else {
/* We have no MBS pathname. Fail. */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname to %s",
archive_string_conversion_charset_name(sconv));
return ARCHIVE_FAILED;
}
} }
if (copy_length <= USTAR_name_size) if (copy_length <= USTAR_name_size)
memcpy(h + USTAR_name_offset, pp, copy_length); memcpy(h + USTAR_name_offset, pp, copy_length);
@@ -232,7 +232,11 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry)
sconv = v7tar->opt_sconv; sconv = v7tar->opt_sconv;
/* Sanity check. */ /* Sanity check. */
if (archive_entry_pathname(entry) == NULL) { if (archive_entry_pathname(entry) == NULL
#if defined(_WIN32) && !defined(__CYGWIN__)
&& archive_entry_pathname_w(entry) == NULL
#endif
) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't record entry in tar file without pathname"); "Can't record entry in tar file without pathname");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
@@ -382,15 +386,28 @@ format_header_v7tar(struct archive_write *a, char h[512],
*/ */
r = archive_entry_pathname_l(entry, &pp, &copy_length, sconv); r = archive_entry_pathname_l(entry, &pp, &copy_length, sconv);
if (r != 0) { if (r != 0) {
const char* p_mbs;
if (errno == ENOMEM) { if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Pathname"); "Can't allocate memory for Pathname");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
p_mbs = archive_entry_pathname(entry);
if (p_mbs) {
/* We have a wrongly-encoded MBS pathname.
* Warn and use it. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname '%s' to %s", "Can't translate pathname '%s' to %s", p_mbs,
pp, archive_string_conversion_charset_name(sconv)); archive_string_conversion_charset_name(sconv));
ret = ARCHIVE_WARN; ret = ARCHIVE_WARN;
} else {
/* We have no MBS pathname. Fail. */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname to %s",
archive_string_conversion_charset_name(sconv));
return ARCHIVE_FAILED;
}
} }
if (strict && copy_length < V7TAR_name_size) if (strict && copy_length < V7TAR_name_size)
memcpy(h + V7TAR_name_offset, pp, copy_length); memcpy(h + V7TAR_name_offset, pp, copy_length);
@@ -526,12 +526,13 @@ xar_options(struct archive_write *a, const char *key, const char *value)
} }
if (strcmp(key, "threads") == 0) { if (strcmp(key, "threads") == 0) {
char *endptr; char *endptr;
unsigned long val;
if (value == NULL) if (value == NULL)
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
errno = 0; errno = 0;
xar->opt_threads = (int)strtoul(value, &endptr, 10); val = strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0') { if (errno != 0 || *endptr != '\0' || val > (unsigned)INT_MAX) {
xar->opt_threads = 1; xar->opt_threads = 1;
archive_set_error(&(a->archive), archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC, ARCHIVE_ERRNO_MISC,
@@ -539,6 +540,7 @@ xar_options(struct archive_write *a, const char *key, const char *value)
value); value);
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
xar->opt_threads = (int)val;
if (xar->opt_threads == 0) { if (xar->opt_threads == 0) {
#ifdef HAVE_LZMA_STREAM_ENCODER_MT #ifdef HAVE_LZMA_STREAM_ENCODER_MT
xar->opt_threads = lzma_cputhreads(); xar->opt_threads = lzma_cputhreads();
@@ -398,16 +398,17 @@ archive_write_zip_options(struct archive_write *a, const char *key,
return (ret); return (ret);
} else if (strcmp(key, "compression-level") == 0) { } else if (strcmp(key, "compression-level") == 0) {
char *endptr; char *endptr;
unsigned long v;
if (val == NULL) if (val == NULL)
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
errno = 0; errno = 0;
zip->compression_level = (short)strtoul(val, &endptr, 10); v = strtoul(val, &endptr, 10);
if (errno != 0 || *endptr != '\0' || zip->compression_level < 0 || if (errno != 0 || *endptr != '\0' || v > 9) {
zip->compression_level > 9) {
zip->compression_level = 6; // set to default zip->compression_level = 6; // set to default
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
} }
zip->compression_level = (short)v;
if (zip->compression_level == 0) { if (zip->compression_level == 0) {
zip->requested_compression = COMPRESSION_STORE; zip->requested_compression = COMPRESSION_STORE;
@@ -435,17 +436,19 @@ archive_write_zip_options(struct archive_write *a, const char *key,
} }
} else if (strcmp(key, "threads") == 0) { } else if (strcmp(key, "threads") == 0) {
char *endptr; char *endptr;
unsigned long v;
if (val == NULL) if (val == NULL)
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
errno = 0; errno = 0;
zip->threads = (short)strtoul(val, &endptr, 10); v = strtoul(val, &endptr, 10);
if (errno != 0 || *endptr != '\0') { if (errno != 0 || *endptr != '\0' || v > SHRT_MAX) {
zip->threads = 1; zip->threads = 1;
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Illegal value `%s'", val); "Illegal value `%s'", val);
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
} }
zip->threads = (short)v;
if (zip->threads == 0) { if (zip->threads == 0) {
#ifdef HAVE_LZMA_STREAM_ENCODER_MT #ifdef HAVE_LZMA_STREAM_ENCODER_MT
zip->threads = lzma_cputhreads(); zip->threads = lzma_cputhreads();
@@ -802,6 +805,17 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
int version_needed = 10; int version_needed = 10;
#define MIN_VERSION_NEEDED(x) do { if (version_needed < x) { version_needed = x; } } while (0) #define MIN_VERSION_NEEDED(x) do { if (version_needed < x) { version_needed = x; } } while (0)
/* Sanity check. */
if (archive_entry_pathname(entry) == NULL
#if defined(_WIN32) && !defined(__CYGWIN__)
&& archive_entry_pathname_w(entry) == NULL
#endif
) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't record entry in zip file without pathname");
return ARCHIVE_FAILED;
}
/* Ignore types of entries that we don't support. */ /* Ignore types of entries that we don't support. */
type = archive_entry_filetype(entry); type = archive_entry_filetype(entry);
if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) {
@@ -882,22 +896,33 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
if (sconv != NULL) { {
const char *p; const char *p;
size_t len; size_t len;
if (archive_entry_pathname_l(zip->entry, &p, &len, sconv) != 0) { if (archive_entry_pathname_l(zip->entry, &p, &len, sconv) != 0) {
const char* p_mbs;
if (errno == ENOMEM) { if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Pathname"); "Can't allocate memory for Pathname");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
p_mbs = archive_entry_pathname(zip->entry);
if (p_mbs) {
/* We have a wrongly-encoded MBS pathname. Warn and use it. */
archive_set_error(&a->archive, archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate Pathname '%s' to %s", "Can't translate pathname '%s' to %s", p_mbs,
archive_entry_pathname(zip->entry),
archive_string_conversion_charset_name(sconv)); archive_string_conversion_charset_name(sconv));
ret2 = ARCHIVE_WARN; ret2 = ARCHIVE_WARN;
} else {
/* We have no MBS pathname. Fail. */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname to %s",
archive_string_conversion_charset_name(sconv));
return ARCHIVE_FAILED;
}
} }
if (len > 0) if (len > 0)
archive_entry_set_pathname(zip->entry, p); archive_entry_set_pathname(zip->entry, p);
@@ -404,6 +404,29 @@ DEFINE_TEST(test_acl_from_text)
archive_entry_acl_clear(ae); archive_entry_acl_clear(ae);
free(ws); free(ws);
/*
* 6. Malformed "default" prefix with no tag field should return
* ARCHIVE_WARN, not crash (GitHub issue #2744).
* When the ACL text is just "d" or "default" with type DEFAULT,
* the parser recognises the default prefix but field[1] is NULL,
* which previously caused a NULL-pointer dereference.
*/
archive_entry_acl_clear(ae);
assertEqualInt(ARCHIVE_WARN,
archive_entry_acl_from_text(ae, "d",
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
assertEqualInt(ARCHIVE_WARN,
archive_entry_acl_from_text_w(ae, L"d",
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
archive_entry_acl_clear(ae);
assertEqualInt(ARCHIVE_WARN,
archive_entry_acl_from_text(ae, "default",
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
assertEqualInt(ARCHIVE_WARN,
archive_entry_acl_from_text_w(ae, L"default",
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
archive_entry_free(ae); archive_entry_free(ae);
} }
@@ -285,4 +285,22 @@ DEFINE_TEST(test_archive_pathmatch)
archive_pathmatch("a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); archive_pathmatch("a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1, assertEqualInt(1,
archive_pathmatch("b/c/d$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); archive_pathmatch("b/c/d$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
/* Anchor characters within pattern not special. */
assertEqualInt(0,
archive_pathmatch("*^*", "a/b/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
archive_pathmatch("*^*", "a^b", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
assertEqualInt(0,
archive_pathmatch("*$*", "a/b/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
archive_pathmatch("*$*", "a$b", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
assertEqualInt(0,
archive_pathmatch("a*/^b/c", "a/b/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
archive_pathmatch("a*/^b/c", "a/^b/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
assertEqualInt(0,
archive_pathmatch("a*/b$/c", "a/b/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
archive_pathmatch("a*/b$/c", "a/b$/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
} }
@@ -883,6 +883,141 @@ DEFINE_TEST(test_archive_string_conversion)
test_archive_string_set_get(); test_archive_string_set_get();
} }
static void
test_archive_string_conversion_fail_charset(void)
{
/* Conversion error message construction may use the charset name. */
assertEqualString("current locale",
archive_string_conversion_charset_name(NULL));
}
static void
test_archive_string_conversion_fail_utf16_mbs(struct archive *a,
struct archive_string_conv *sconv)
{
static const wchar_t wcs_string[] = L"\U0000043f\U00000440\U00000438";
int r;
const char* p;
size_t len;
/* WCS to MBS should fail. */
{
struct archive_string str;
archive_string_init(&str);
r = archive_string_append_from_wcs(
&str, wcs_string, sizeof(wcs_string) / sizeof(*wcs_string) - 1);
assertEqualInt(-1, r);
archive_string_free(&str);
}
{
struct archive_mstring mstr;
memset(&mstr, 0, sizeof(mstr));
assertEqualInt(ARCHIVE_OK,
archive_mstring_copy_wcs(&mstr, wcs_string));
r = archive_mstring_get_mbs_l(a, &mstr, &p, &len, NULL);
assertEqualInt(-1, r);
assertEqualInt(0, mstr.aes_set & AES_SET_MBS);
archive_mstring_clean(&mstr);
}
if (sconv) {
struct archive_mstring mstr;
memset(&mstr, 0, sizeof(mstr));
assertEqualInt(ARCHIVE_OK,
archive_mstring_copy_wcs(&mstr, wcs_string));
r = archive_mstring_get_mbs_l(a, &mstr, &p, &len, sconv);
assertEqualInt(-1, r);
assertEqualInt(0, mstr.aes_set & AES_SET_MBS);
archive_mstring_clean(&mstr);
}
}
static void
test_archive_string_conversion_fail_utf8_mbs(struct archive *a,
struct archive_string_conv *sconv)
{
static const char utf8_string[] = "\xD0\xBF\xD1\x80\xD0\xB8";
int r;
const char* p;
size_t len;
/* UTF-8 to MBS should fail. */
{
struct archive_mstring mstr;
memset(&mstr, 0, sizeof(mstr));
assertEqualInt(6,
archive_mstring_copy_utf8(&mstr, utf8_string));
r = archive_mstring_get_mbs_l(a, &mstr, &p, &len, NULL);
assertEqualInt(-1, r);
assertEqualInt(0, mstr.aes_set & AES_SET_MBS);
archive_mstring_clean(&mstr);
}
if (sconv) {
struct archive_mstring mstr;
memset(&mstr, 0, sizeof(mstr));
assertEqualInt(6,
archive_mstring_copy_utf8(&mstr, utf8_string));
r = archive_mstring_get_mbs_l(a, &mstr, &p, &len, sconv);
assertEqualInt(-1, r);
assertEqualInt(0, mstr.aes_set & AES_SET_MBS);
archive_mstring_clean(&mstr);
}
}
DEFINE_TEST(test_archive_string_conversion_fail_c)
{
struct archive *a;
/* Test the C locale by not calling setlocale. */
test_archive_string_conversion_fail_charset();
assert((a = archive_write_new()) != NULL);
test_archive_string_conversion_fail_utf16_mbs(a, NULL);
test_archive_string_conversion_fail_utf8_mbs(a, NULL);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
}
DEFINE_TEST(test_archive_string_conversion_fail_latin1)
{
struct archive *a;
struct archive_string_conv *sconv;
/* Test a Latin-1 locale. */
if (
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Windows allows ".<code-page>" to change encoding. */
setlocale(LC_ALL, ".1252") == NULL
#else
setlocale(LC_ALL, "en_US.ISO8859-1") == NULL
#endif
) {
skipping("No Latin-1 locale found on this system.");
return;
}
test_archive_string_conversion_fail_charset();
assert((a = archive_write_new()) != NULL);
#if defined(_WIN32) && !defined(__CYGWIN__)
assertA(NULL != (sconv =
archive_string_conversion_to_charset(a, "CP1252", 0)));
assertEqualString("CP1252",
archive_string_conversion_charset_name(sconv));
#else
assertA(NULL != (sconv =
archive_string_conversion_to_charset(a, "ISO8859-1", 0)));
assertEqualString("ISO8859-1",
archive_string_conversion_charset_name(sconv));
#endif
test_archive_string_conversion_fail_utf16_mbs(a, sconv);
test_archive_string_conversion_fail_utf8_mbs(a, sconv);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
}
DEFINE_TEST(test_archive_string_conversion_utf16_utf8) DEFINE_TEST(test_archive_string_conversion_utf16_utf8)
{ {
#if !defined(_WIN32) || defined(__CYGWIN__) #if !defined(_WIN32) || defined(__CYGWIN__)
@@ -491,3 +491,43 @@ DEFINE_TEST(test_gnutar_filename_encoding_UTF16_win)
assertEqualMem(buff + 157, "\xE8\xA1\xA8.txt", 7); assertEqualMem(buff + 157, "\xE8\xA1\xA8.txt", 7);
#endif #endif
} }
DEFINE_TEST(test_gnutar_filename_encoding_fail_UTF16_win)
{
#if !defined(_WIN32) || defined(__CYGWIN__)
skipping("This test is meant to verify unicode string handling"
" on Windows with UTF-16 names");
return;
#else
struct archive *a;
struct archive_entry *entry;
char buff[4096];
size_t used;
/* Test the C locale by not calling setlocale. */
a = archive_write_new();
assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a));
if (archive_write_set_options(a, "hdrcharset=CP437") != ARCHIVE_OK) {
skipping("This system cannot convert character-set"
" from UTF-16 to CP437.");
archive_write_free(a);
return;
}
assertEqualInt(ARCHIVE_OK,
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
/* Set the filename using a UTF-16 string */
archive_entry_copy_pathname_w(entry, L"\u8868.txt");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, entry));
/* The pathname cannot even be represented in the current locale
for inclusion in the error message. */
assertEqualString("Can't translate pathname to CP437",
archive_error_string(a));
archive_entry_free(entry);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
#endif
}
@@ -1383,6 +1383,32 @@ DEFINE_TEST(test_read_format_7zip_sfx_elf)
assertEqualInt(ARCHIVE_OK, archive_read_free(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a));
} }
/*
* A truncated ELF 64-bit MSB file.
*/
DEFINE_TEST(test_read_format_7zip_sfx_elf64trunc)
{
const char *reffile = "test_read_format_7zip_sfx_elf64trunc.elf";
struct archive_entry *ae;
struct archive *a;
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));
extract_reference_file(reffile);
assertEqualIntA(a, ARCHIVE_FATAL,
archive_read_open_filename(a, reffile, 10240));
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
assertEqualInt(0, archive_file_count(a));
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_format_7zip_extract_second) DEFINE_TEST(test_read_format_7zip_extract_second)
{ {
struct archive *a; struct archive *a;
@@ -59,8 +59,25 @@ test_malformed2(void)
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
} }
static void
test_malformed3(void)
{
const char *refname = "test_read_format_7zip_malformed3.7z";
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));
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_format_7zip_malformed) DEFINE_TEST(test_read_format_7zip_malformed)
{ {
test_malformed1(); test_malformed1();
test_malformed2(); test_malformed2();
test_malformed3();
} }
@@ -0,0 +1,24 @@
begin 644 test_read_format_7zip_malformed3.7z
M?T5,1@("`64N9&5B=0``+ZZNRO_______P```/\Q```````````"````````
M```L0"!S+F)S,``1<P!```H``FMK__](:VMK:VNAH:$!`*&AH:&A)S$```!C
M;VUP>FEP503_8G-S90``````#0H-_P```'X```````````(`````````````
M`*D``````"\`````____^@````$````````#`/__________<RYD96)U```O
MKJ[*________````_S$```````````(``````````"Q`(',N8G,P`!%S`$``
M(``":VNAH2<Q```````#Z'K__P5%145%____________`/__________;VUP
M>FEP503_8G-S90``````#0H-_P```'X```````````(``````````````*D`
M`````"\`````____^@````$````````#_P```/______<RYD96)U```OKJ[*
M________````_S$```````````(``````````"Q`(',N8G,P`!%S`$"0`P`"
M:VLR:TAK:VMK:Z&AH0$`H:&AH:$G,@```&-O;7!Z:7!5!/]28W-E```````-
M"@W_````?@```````````@``````````````J0``````+P`````0___Z````
M`0````````,`__________\PXT$N9&%T80#^E)3+E)24_P3_____________
M____(________^+______P5%145%____________`/__________________
M_____________________^?_________145%0``#`/Z4E,N4P<'!P<'!E```
M`/_R`````'5U=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U
M=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U=0`````"````
M```````L0"!S+F4```````T*#?\```!^```````````"``````````````"I
M```````O`````/___^0````!`````````P#__W5U=75U=75U=75U=75U=75U
M=0`````"```````````L0"!S+F)S,?P1<P!```,`"&MK,FM(:VMK145%145%
,P45%145%1?____\$
`
end
@@ -0,0 +1,5 @@
begin 664 test_read_format_7zip_sfx_elf64trunc.elf
M?T5,1@("````````````````````````````````````````````````````
2```````````````````H``$`
`
end
@@ -0,0 +1,45 @@
#include "test.h"
/*
* Regression test for Heap Out-of-Bounds Write in CAB LZX decoder.
* This ensures that a malformed CFDATA uncompressed size does not
* bypass physical buffer limits and cause memory corruption during skips.
*/
DEFINE_TEST(test_read_format_cab_lzx_oob)
{
const char *refname = "test_read_format_cab_lzx_oob.cab";
struct archive *a;
struct archive_entry *ae;
const void *buff;
size_t size;
int64_t offset;
/* * The test framework will automatically find 'test_read_format_cab_lzx_oob.cab.uu',
* decode it, and place the binary '.cab' in the temporary test directory.
*/
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_cab(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
/* If it fails to open, there's a problem with the test setup/file */
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
/* Read the header of the malformed entry */
if (ARCHIVE_OK == archive_read_next_header(a, &ae)) {
/* * We attempt to read a block to initialize the LZX state machine.
* We do not assert the result because the file is intentionally malformed.
* Regardless of success or failure, we force a skip to test state handling
* and trigger the vulnerability.
*/
archive_read_data_block(a, &buff, &size, &offset);
archive_read_data_skip(a);
/* * Optional: We could assert that the error string contains our patch message,
* but simply surviving without a segfault/ASAN violation is the primary goal
* for fuzzing regression tests.
*/
}
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
@@ -0,0 +1,11 @@
begin 664 test_read_format_cab_lzx_oob.cab
M35-#1@````!!``"2DI*2DI(````````2Y``!``$``,2PW@``'P$```$`0Q`!
M`3O2T@D)"0D)"0D)``````````````"RLK*RLK*RLK*RLK*RLK*RLK(*,```
M````````````````LK*2X____[:RL@``````````LK*R"C``````````````
M`````+*RDN/___^VLK(```````````"R'YV)3``````````````0$!`0$!`0
M$!`0$!D0$!`0$!`0$!`0$!`0$!`0$!#___\/$!`0`````````$`0$`!`,#<P
M-S`R````,#82SWXO+R\`_P``````````````````````````````````````
M``````#U\DH*-S`R````,#82SWXO+R\`_P``````````````````````````
.````````````````````
`
end
@@ -0,0 +1,41 @@
#include "test.h"
DEFINE_TEST(test_read_format_cab_skip_malformed)
{
/* Reference to the malformed CAB file */
const char *refname = "test_read_format_cab_skip_malformed.cab";
struct archive *a;
struct archive_entry *ae;
void *buffer;
size_t buffersize;
/* Extract the reference file into the test sandbox */
extract_reference_file(refname);
/* Read the entire file into memory */
buffer = slurpfile(&buffersize, "%s", refname);
assert(buffer != NULL);
/* Initialize the archive reader */
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
/* Read from memory (a prerequisite for triggering this specific bug) */
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buffer, buffersize));
/* Simulate the parsing flow to trigger the implicit skip routine */
while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
const void *buff;
size_t size_read;
int64_t offset;
while (archive_read_data_block(a, &buff, &size_read, &offset) == ARCHIVE_OK) {
/* Consume data. This will fail quickly due to the malformed payload. */
}
}
/* Clean up. If the patch is effective, the program reaches here safely. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
free(buffer);
}
@@ -0,0 +1,95 @@
begin 664 test_read_format_cab_skip_malformed.cab
M35-#1@````!!``"2DI*2DI(````````2Y``!``$``,2PW@``'P$``-(!```!
M.]+2"0D)"0D)"0D)"0D)"0D)"0FRLK*R"0D)"0D)"0D)"0D)LK*RLK*RLK(`
M``````````````````"RLK*RLK*RLK*RLK*RLK*RLK(*,```````````````
M````LK*RX____[:RL@```````````````#`W,"]`````"G!P`````&UDL@HP
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````%!+`P0````!#`P,#`P,#`P,#`P,#```````````````__\```3_
M``!(___H````````````````````````````````````````____________
M____________________________________________________````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M@```````````````@`````$`````````````````````````````````````
M````````````````````````````````````````````#`H,#````'H,#`P`
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````#__P``!/\``$C__^@```````````#_________________________
M______________________________________\`````````````````````
M`"\O+R\O+R\O+R\O+R\O+R\O+R\O+R\G+PHQ-C4P+U):22\P-S!,4EI)"@HO
M=6YS970@<F$@("T@("!/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T\@(2`@("`@
M+2`@("`@("`@(",@("`@("`@("L@("`@("`@("`@("`@("`@("`@("`@("`@
M("`K('A,4EI)"@H*("`@("`@(```````````````````````````````````
M```````````````````````````````````````````````````,]@P,#`H*
M````````````````````````````````````````````````````````````
M``````````````````````````````````````#__P``!/\``$C__^@`````
M`%``````````````````````````````````________________________
M________________________________________````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````@```````
M````````@`````$`````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````#__P``!/\``$C__^@`
M``````````#_________________________________________________
M______________\`````````````````````````````````````````````
M`````````````````````%!+`P0````!#`P,#`P,#`P,#`P,#```#`H,#```
M`'H,````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````,#`SV``````````````````````P,
M#`H*`/__```$_P``2/__Z````````````%#_________________________
M______________________________________\`````````````````````
M````````````````````````````````````````````+R\P23@*"DQ:3#`P
M"DQ26DD*"DQ:+PH*,#`W,"\O,#<P+R\O+R\O+S!).`H*3%I,,"\P-S!,4EI)
M"@I,6B\O"F)E9VEN-F%E<RUB-"`Q(%TP-#`P5T%20R\O25HX"DQ,,`I,4EI)
M"@I,6B\O-S`W"DQ:3#`O,#<P3%):20H*3%HO+PIB96=I;BUB87-E-C0@-B`P
M-#`P5T%20R\O25HX"DQ,,`I,4EI)"@I,6B\O-S`W,#<O+R]:4B\O+R\O"C!@
M-S`W,#$*#8V-C8V-C8V-C8V-C8V-C8V-C5!+`P10"@`*"C`P-S`O+S`W,"\O
M+R\O+R\P23@*"DQ:3#`O,#<P3%):20H*3%HO+PIB96=I;BUB87-E-C0@,2`P
M-#`P5T%20R\O25HX"DQ,"DQ:3#`O,#<P3%):20H*3%HO+PIB96=I;BUB87-E
M-C0@,2`P-#`P5T%20R\O25HV"DQ,,`I,4EI)"@I,6B\*"C`P-S`O+S`W,"\O
M+R\O+R\P23@*"DQ:3#`O,#<P3%):20H*3%HO+PIB90``V/\M`?\-__\-_RO_
M_?____\F__\+____B?\*)PH``')R<G)R<G)R<G+_____________________
M____________________________________________________________
M____________________________________________________________
M____________________________________________________<G)R<G)R
M<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)``!0`
M`````````````````$#_____"`1W2"__0`#D$P`G_D3________NXEQ<7%QR
M7#`P-S=<,#)<7%Q<7%Q<?%Q<7%Q<<EPP,#<W7#`R7%Q<7%Q<7%Q<,#)<7%Q<
M7%Q<7')<,#`W-UPP,EQ<7%Q<7"L*=75,6B\O"F)E9VEN+6)A<V4V-"`V(#`T
M,#!705)#+R])6C@*3"`Q(#`T,#!705)#+R])6C@*3$P*3%I,,"\P-S!,4EI)
M"@I,6B\O"F)E9VEN+6)A<V4V-"`Q(#`T,#!705)#+R])6C@*3$PP"DQ26DD*
M"DQ:+PH*,#`W,"\O,#<P+R\O+R\O+S!).`H*3%I,,"\P-S!,4EI)"@I,6B\O
M"F)E9VEN+6)A<V4V-"`Q,S`T,#!705)#+R])6C@*3$PP"DQ26DD*"DQ:+R\W
M,#<*3%I,,"\P-S!,4EI)"@I,6B\O"F)E9VEN+6)A<V4V-"`V(#`T,#!705)#
M+R])6C@*3$PP"DQ26DD*"DQ:+R\W,#<P-R\O+UI2+R\O+R\O+R\O-S`W"DQ:
M3#`O04Y325\P-S!,4EI)"@I,6B\O"F)E9VEN+6)A<V4V-"`V(#`T,#!705)#
M+R])6CP*3$PP"DQ26DD*"DQ:+R\W,#<P-R\O+UI2+R\O+R\O+R\O+R\O+R\O
M+R\O+R\O+R\O+R\P23@*"DQ:3"\O+R\O+R\P23@*"DQ:3#`O,#<P3%):20H*
M3%HO+PIB96=I;BUB87-E-C0@,2`P-#`P5T%20R\O25HX"DQ,,`I,4EI)"@I,
M6B\O-S`W"DQ:3#`O,#<P3%):20H*3%HO+PIB96=I;BUB87-/-C0@-B`P-#`P
M5T%20R\O25HX"DQ,,`I,4EI)"@I,6B\O-S`W,#<O+R]:4B\O+R\O+R\O+S<P
M-PI,6DPP+S`W,$Q26DD*"DQ:+R\*8F5G:6XM8F%S938T(#8@,#0P,%=!4D,O
M,#<P3%):20H*3%HO+PIB96=I;BUB87-E-C0@,2!=,#0P,%=!4D,O+TE:.`I,
M3#`*3%):20H*3%HO+S<P-PI,6DPP+S`W,$Q26DD*"DQ:+R\*8F5G:6XM8F%S
M938T(#8@,#0P,%=!4D,O+TE:.`I,3#`*3%):20H*,!^+#@``````````````
M```````+``````#'<?\```````````L``````,=Q_____U):20```````!`D
M````````3%HO+S<P-S`W+R\O6E(O+R]Z+R\*,&`W,#<P,0H-"@U=2@T*#0HN
M+@H*#0!$`````%Q<7%QA7%Q<55Q<05PR*5Q<7%Q<7%Q<7%PP7%Q!7#(I7%Q<
M7%Q<7%Q<7#!<7$%<,BE<7%Q<85Q<7%5<7$%<,BE<7%Q<7%Q<7%Q<,%Q<7%Q<
M7%Q<7%Q57%Q!7#(I7`D)"0D)"0D)"0D)"0D)"0D)"0D)"@````!%1@"']@``
!````
`
end
@@ -0,0 +1,104 @@
/*-
* Copyright (c) 2025
* 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"
/*
* Verify that a crafted ISO9660 image with an invalid zisofs block-size
* exponent (pz_log2_bs) is handled gracefully.
*
* The ZF extension in the Rock Ridge entry stores pz_log2_bs as a raw
* byte from the image. The zisofs spec only permits values 15-17.
* Values outside that range can cause:
* - Undefined behavior via oversized bit shifts (any platform)
* - Integer overflow in block pointer allocation on 32-bit platforms,
* leading to a heap buffer overflow write
*
* The test image has pz_log2_bs=2 (out of spec) combined with
* pz_uncompressed_size=0xFFFFFFF9. On 32-bit, (ceil+1)*4 overflows
* size_t to 0, malloc(0) returns a tiny buffer, and the code attempts
* to write ~4GB into it. On 64-bit the allocation is huge and safely
* fails.
*
* We verify the fix by checking archive_entry_size() after reading the
* header. When pz_log2_bs validation rejects the bad value (pz=0),
* the entry keeps its raw on-disk size (small). Without the fix,
* the reader sets the entry size to pz_uncompressed_size (0xFFFFFFF9).
*
* We intentionally do NOT call archive_read_data() here. Without the
* fix, the data-read path triggers a heap buffer overflow on 32-bit
* that silently corrupts the process heap, causing later tests to
* crash rather than this one.
*/
DEFINE_TEST(test_read_format_iso_zisofs_overflow)
{
const char reffile[] = "test_read_format_iso_zisofs_overflow.iso";
struct archive *a;
struct archive_entry *ae;
int r = ARCHIVE_OK;
int found_regular_file = 0;
extract_reference_file(reffile);
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_OK,
archive_read_open_filename(a, reffile, 10240));
while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK ||
r == ARCHIVE_WARN) {
/*
* With the fix, pz_log2_bs=2 is rejected and pz is set
* to 0, so the entry keeps its small raw size from the
* ISO directory record. Without the fix, zisofs sets
* the entry size to pz_uncompressed_size (0xFFFFFFF9).
*
* We intentionally do NOT call archive_read_data().
* Without the fix, the data-read path triggers a heap
* buffer overflow on 32-bit that silently corrupts the
* process heap, causing later tests to crash rather
* than this one.
*/
if (archive_entry_filetype(ae) == AE_IFREG) {
la_int64_t sz = archive_entry_size(ae);
failure("entry \"%s\" has size %jd"
"; expected < 1 MiB"
" (if size is 4294966265 = 0xFFFFFFF9, the"
" pz_log2_bs validation is missing)",
archive_entry_pathname(ae), (intmax_t)sz);
assert(sz < 1024 * 1024);
found_regular_file = 1;
}
}
/* Iteration must have completed normally. */
assertEqualInt(ARCHIVE_EOF, r);
/* The PoC image contains a regular file; if we never saw one,
* something is wrong with the test image. */
assert(found_regular_file);
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,50 @@
/*-
* Copyright (c) 2026 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"
DEFINE_TEST(test_read_format_lha_oversize_header)
{
const char *refname = "test_read_format_lha_oversize_header.lzh";
extract_reference_file(refname);
struct archive_entry *ae;
struct archive *a;
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
/* First 18 entries in the test file are well-formed */
for (int i = 0; i < 18; i++) {
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
}
/* 19th has an oversized header */
assertEqualInt(ARCHIVE_FATAL, archive_read_next_header(a, &ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
@@ -0,0 +1,60 @@
begin 644 test_read_format_lha_oversize_header.lzh
M)L`M;&AD+0```````````$@B[!``!&1I<EP``%4`@5$!`.A!Z0/I`R?X+6QH
M9"T```````````!((NP0``5D:7(R7```50"!40$`[4'I`^D#.'PM;&AD+0``
M`````````4@C[!``%F1I<C)<<WEM;&EN:S%\+BY<9FEL93$``%4``J,"`.VA
MZ0/I`SA^+6QH9"T```````````%((^P0`!9D:7(R7'-Y;6QI;FLR?"XN7&9I
M;&4R``!5``*C`@#MH>D#Z0,GO2UL:#4M(@```#P`````2"+L(``%9FEL93&D
MYU4`@5$!`*2!Z0/I`P`80FYIQ>/Z`=-:'>9%#"P%J!\CH0"/GE$,.W6FMSD%
M*_4G02UL:#4M(@```$X`````2"+L(``%9FEL93+5%54`@5$!`+:!Z0/I`P`8
M0FYIQV/Z`=.:'.9%#"P%J-\+H0"/'E$,.W6FMSD%*_T9?RUL:&0M&@``````
M````2"+L(`$```!5!P`"9&ER_P4`4.A!!P!1Z0/I`P<`5(%1`0```!F!+6QH
M9"T;``````````!((NP@`0```%4(``)D:7(R_P4`4.U!!P!1Z0/I`P<`5(%1
M`0```!YQ+6QH9"TG``````````%((^P@`05F:6QE,0``510``F1I<C+_<WEM
M;&EN:S%\+B[_!0!0[:$'`%'I`^D#!P!4`J,"````'G(M;&AD+2<`````````
M`4@C["`!!69I;&4R``!5%``"9&ER,O]S>6UL:6YK,GPN+O\%`%#MH0<`4>D#
MZ0,'`%0"HP(````>!BUL:#4M-0```#P`````2"+L(`$%9FEL93&DYU4%`%"D
M@0<`4>D#Z0,'`%2!40$`````&$)N:<7C^@'36AWF10PL!:@?(Z$`CYY1##MU
MIK<Y!2OU'G@M;&@U+34```!.`````$@B["`!!69I;&4RU155!0!0MH$'`%'I
M`^D#!P!4@5$!`````!A";FG'8_H!TYH<YD4,+`6HWPNA`(\>40P[=::W.04K
M_34`+6QH9"T``````````(%1`0`@`@``504```7>`P`!!P`"9&ER_P4`4.A!
M!P!1Z0/I`P``-@`M;&AD+0``````````@5$!`"`"``!5!0``")D#``$(``)D
M:7(R_P4`4.U!!P!1Z0/I`P``1P`M;&AD+0```````````J,"`"`"``!5!0``
MM*D(``%F:6QE,10``F1I<C+_<WEM;&EN:S%\+B[_!0!0[:$'`%'I`^D#``!'
M`"UL:&0M```````````"HP(`(`(``%4%``"'[0@``69I;&4R%``"9&ER,O]S
M>6UL:6YK,GPN+O\%`%#MH0<`4>D#Z0,``#,`+6QH-2TB````/````(%1`0`@
M`J3G504``/T!"``!9FEL93$%`%"D@0<`4>D#Z0,````80FYIQ>/Z`=-:'>9%
M#"P%J!\CH0"/GE$,.W6FMSD%*_4S`"UL:#4M(@```$X```"!40$`(`+5%54%
M```OQ@@``69I;&4R!0!0MH$'`%'I`^D#````&$)N:<=C^@'3FASF10PL!:C?
M"Z$`CQY1##MUIK<Y!2O]!``M;&AD+0``````````@5$!`"`#``!-?/[___\`
M````````````````````````````````````````````````````````````
M`````````````````````````````````````$:D`P``!0````$)`````F1I
M<O\'````0!``&0```/_M00`````````````,%?Y,1!K^3!T```!!S-]1M/Z5
MRP&`UD``J+*=`0!Z#]`!ELL!"``````NKP<`````!``M;&AD+0``````````
M@5$!`"`#``!-?0````D```!&I`,```4````!"@````)D:7(R_P<```!`$``9
M````_^U!`````````````"$:_DQ$&OY,'0```$%*@6Z[`9;+`8#60`"HLIT!
M`'H/T`&6RP$(`````'T7!P`````$`"UL:#4M)````#P```"!40$`(`.DYTUQ
M````"0```$:D`P``"@````%F:6QE,1D```#_I($`````````````QQ3^3",:
M_DP=````031"HHK^E<L!@-9``*BRG0'^<J2\`9;+`0@`````"O$'```````9
M0FV1J+1V@'IK0ZGID/-H#J@6.H0"'V^-&353:F^XA-UZ@`0`+6QH-2TD````
M3@```(%1`0`@`]4537$````)````1J0#```*`````69I;&4R&0```/^D@0``
M```````````A&OY,(QK^3!T```!!_D5SNP&6RP&`UD``J+*=`5C5IKP!ELL!
M"`````!!W@<``````!E";9&H[':`>G-#B>F0\V@.J,8:A`(>;XT9-5-J;[B$
MW7Z`-0`M;&AD+0``````````@5$!`"`"``!5!40:_DP=````0<S?4;3^E<L!
M@-9``*BRG0$`>@_0`9;+`0@`````+J\'``````0`+6QH9"T``````````(%1
M`0`@`P``37T````)````1J0#```%`````0H````"9&ER,O\'````0!``&0``
M`/_M00`````````````A&OY,1!K^3!T```!!2H%NNP&6RP&`UD``J+*=`0!Z
M#]`!ELL!"`````!]%P<`````!``M;&@U+20````\````@5$!`"`#I.=-<0``
M``D```!&I`,```H````!9FEL93$9````_Z2!`````````````,<4_DPC&OY,
M'0```$$T0J**_I7+`8#60`"HLIT!_G*DO`&6RP$(``````KQ!P``````&4)M
MD:BT=H!Z:T.IZ9!1Z0/I`P```FUK=XVV['"Z\`>$(6[`2-EZ5P&P^!J*0MPV
M*IM]&^L37/)<Y+,0WC;RYN647;X'R_\P`E;2>[SD(6GCE`4$+,RA<%QVYXC%
M'H1Q`I@_B\H/L@(+W3`0@5CY6X%Q%WW+@7<`8(F7=77U]%5YG?`;3N&I:_6Y
MWA$,3F@?:)>FZ!<!"?.:#C/:',\PG@>:WRP0:TH8%&:/A#VMNUUD[D?+:#XK
M%3NMR(PSF4;V"^\X0/E3JMRQ46+7\I]S@7ZJNTX[ROSD+=\7\.O#I:W._S>P
M-B(W4`=N<T/$OT+5];U>*!<4AM0Y4$L'"(=02P,$\$*.O%TM;&@U+0``KPLX
M+4``2@````````"``````/________\`````````V0````"A````````````
M````````````+6QH-RT```!8$,P.0&OJER*:CF[S6/=2*T4J8HB@[:HP^'7*
MK?(\7:Y+-"U'*^OXT210`,J%*>9(T9[(@N(DJ+A)A```3`]%Z8U.^3!F0_G-
17YFUYB_%6DWMSZ8'\Z-^CR@`
`
end
@@ -0,0 +1,53 @@
/*-
* Copyright (c) 2026 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"
DEFINE_TEST(test_read_format_rar5_loop_bug)
{
const char *reffile = "test_read_format_rar5_loop_bug.rar";
struct archive_entry *ae;
struct archive *a;
const void *buf;
size_t size;
la_int64_t offset;
extract_reference_file(reffile);
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_OK, archive_read_open_filename(a, reffile, 10240));
// This has just one entry
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
// Read blocks until the end of the entry
while (ARCHIVE_OK == archive_read_data_block(a, &buf, &size, &offset)) {
}
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_free(a));
}
@@ -0,0 +1,189 @@
begin 644 test_read_format_rar5_loop_bug.rar
M4F%R(1H'`0#%&C,R`P$``)T-9%L.`@+P0`"`@`P`@`,``6'(WFP@`?\7_U/^
M8@!.`B`H````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
5```````````````````Y^;*!`@4`
`
end
@@ -177,6 +177,40 @@ DEFINE_TEST(test_read_append_wrong_filter)
assertEqualInt(ARCHIVE_OK,archive_read_free(a)); assertEqualInt(ARCHIVE_OK,archive_read_free(a));
} }
DEFINE_TEST(test_read_append_lzop_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_LZOP);
if (archive_liblzo2_version() != NULL) {
assertEqualIntA(a, ARCHIVE_OK, r);
} else if (canLzop()) {
// We're using an external program
assertEqualIntA(a, ARCHIVE_WARN, r);
}
archive_read_free(a);
}
DEFINE_TEST(test_read_append_grzip_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_GRZIP);
// Grzip currently always uses an external program.
if (canGrzip()) {
assertEqualIntA(a, ARCHIVE_WARN, r);
}
archive_read_free(a);
}
DEFINE_TEST(test_read_append_filter_program) DEFINE_TEST(test_read_append_filter_program)
{ {
struct archive_entry *ae; struct archive_entry *ae;
@@ -492,3 +492,43 @@ DEFINE_TEST(test_ustar_filename_encoding_UTF16_win)
assertEqualMem(buff + 157, "\xE8\xA1\xA8.txt", 7); assertEqualMem(buff + 157, "\xE8\xA1\xA8.txt", 7);
#endif #endif
} }
DEFINE_TEST(test_ustar_filename_encoding_fail_UTF16_win)
{
#if !defined(_WIN32) || defined(__CYGWIN__)
skipping("This test is meant to verify unicode string handling"
" on Windows with UTF-16 names");
return;
#else
struct archive *a;
struct archive_entry *entry;
char buff[4096];
size_t used;
/* Test the C locale by not calling setlocale. */
a = archive_write_new();
assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a));
if (archive_write_set_options(a, "hdrcharset=CP437") != ARCHIVE_OK) {
skipping("This system cannot convert character-set"
" from UTF-16 to CP437.");
archive_write_free(a);
return;
}
assertEqualInt(ARCHIVE_OK,
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
/* Set the filename using a UTF-16 string */
archive_entry_copy_pathname_w(entry, L"\u8868.txt");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, entry));
/* The pathname cannot even be represented in the current locale
for inclusion in the error message. */
assertEqualString("Can't translate pathname to CP437",
archive_error_string(a));
archive_entry_free(entry);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
#endif
}
@@ -0,0 +1,67 @@
/*-
* Copyright (c) 2003-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"
#include <locale.h>
DEFINE_TEST(test_v7tar_filename_encoding_fail_UTF16_win)
{
#if !defined(_WIN32) || defined(__CYGWIN__)
skipping("This test is meant to verify unicode string handling"
" on Windows with UTF-16 names");
return;
#else
struct archive *a;
struct archive_entry *entry;
char buff[4096];
size_t used;
/* Test the C locale by not calling setlocale. */
a = archive_write_new();
assertEqualInt(ARCHIVE_OK, archive_write_set_format_v7tar(a));
if (archive_write_set_options(a, "hdrcharset=CP437") != ARCHIVE_OK) {
skipping("This system cannot convert character-set"
" from UTF-16 to CP437.");
archive_write_free(a);
return;
}
assertEqualInt(ARCHIVE_OK,
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
/* Set the filename using a UTF-16 string */
archive_entry_copy_pathname_w(entry, L"\u8868.txt");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, entry));
/* The pathname cannot even be represented in the current locale
for inclusion in the error message. */
assertEqualString("Can't translate pathname to CP437",
archive_error_string(a));
archive_entry_free(entry);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
#endif
}
@@ -37,7 +37,7 @@ DEFINE_TEST(test_warn_missing_hardlink_target)
assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
assertEqualInt(ENOENT, archive_errno(a)); assertEqualInt(ENOENT, archive_errno(a));
assertEqualString("Hard-link target 'hardlink-target' does not exist.", assertEqualString("Hard-link target 'hardlink-target' does not exist",
archive_error_string(a)); archive_error_string(a));
archive_entry_free(ae); archive_entry_free(ae);
@@ -233,6 +233,22 @@ static void create_reg_file_win(struct archive_entry *ae, const char *msg)
assertEqualInt(st.st_size, sizeof(data)); assertEqualInt(st.st_size, sizeof(data));
free(fname); free(fname);
} }
#else
static void create_fail(struct archive_entry *ae, int experr,
const char *msg)
{
struct archive *ad;
struct stat st;
/* Write the entry to disk. */
assert((ad = archive_write_disk_new()) != NULL);
failure("%s", msg);
assertEqualIntA(ad, ARCHIVE_FAILED, archive_write_header(ad, ae));
assertEqualIntA(ad, experr, archive_errno(ad));
assertEqualInt(0, archive_write_free(ad));
assertEqualInt(-1, stat(archive_entry_pathname(ae), &st));
assertEqualInt(ENOENT, errno);
}
#endif /* _WIN32 && !__CYGWIN__ */ #endif /* _WIN32 && !__CYGWIN__ */
DEFINE_TEST(test_write_disk) DEFINE_TEST(test_write_disk)
@@ -344,5 +360,18 @@ DEFINE_TEST(test_write_disk)
" with unusable characters in its file name"); " with unusable characters in its file name");
archive_entry_free(ae); archive_entry_free(ae);
free(fullpath); free(fullpath);
#else /* !_WIN32 || __CYGWIN__ */
/* A directory with a /../ in the middle */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "a/b/../b/file");
archive_entry_set_mode(ae, S_IFREG | 0644);
/* First attempt should fail with EACCES */
assertEqualInt(0, mkdir("a", 0111));
create_fail(ae, EACCES,
"Test failing to create parent directory with /../");
/* Now let it succeed */
assertEqualInt(0, chmod("a", 0755));
create(ae, "Test creating parent directory with /../");
archive_entry_free(ae);
#endif /* _WIN32 && !__CYGWIN__ */ #endif /* _WIN32 && !__CYGWIN__ */
} }
@@ -26,6 +26,13 @@
#if !defined(_WIN32) || defined(__CYGWIN__) #if !defined(_WIN32) || defined(__CYGWIN__)
#ifdef HAVE_GETEUID
#define getuid() geteuid()
#endif
#ifdef HAVE_GETEGID
#define getgid() getegid()
#endif
#define UMASK 022 #define UMASK 022
static long _default_gid = -1; static long _default_gid = -1;
@@ -142,7 +149,7 @@ DEFINE_TEST(test_write_disk_perms)
* and we're on a system where group ownership is inherited. * and we're on a system where group ownership is inherited.
* (Because we're not allowed to SGID files with defaultgid().) * (Because we're not allowed to SGID files with defaultgid().)
*/ */
assertEqualInt(0, chown(".", getuid(), getgid())); assertChown(".", getuid(), getgid());
/* Create an archive_write_disk object. */ /* Create an archive_write_disk object. */
assert((a = archive_write_disk_new()) != NULL); assert((a = archive_write_disk_new()) != NULL);
@@ -208,7 +215,7 @@ DEFINE_TEST(test_write_disk_perms)
if (getuid() == 0) { if (getuid() == 0) {
original_uid = getuid() + 1; original_uid = getuid() + 1;
try_to_change_uid = getuid(); try_to_change_uid = getuid();
assertEqualInt(0, chown("dir_owner", original_uid, getgid())); assertChown("dir_owner", original_uid, getgid());
} else { } else {
original_uid = getuid(); original_uid = getuid();
try_to_change_uid = getuid() + 1; try_to_change_uid = getuid() + 1;
@@ -622,3 +622,43 @@ DEFINE_TEST(test_zip_filename_encoding_UTF16_win)
/* NOTE: ZIP does not support hardlinks */ /* NOTE: ZIP does not support hardlinks */
#endif #endif
} }
DEFINE_TEST(test_zip_filename_encoding_fail_UTF16_win)
{
#if !defined(_WIN32) || defined(__CYGWIN__)
skipping("This test is meant to verify unicode string handling"
" on Windows with UTF-16 names");
return;
#else
struct archive *a;
struct archive_entry *entry;
char buff[4096];
size_t used;
/* Test the C locale by not calling setlocale. */
a = archive_write_new();
assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a));
if (archive_write_set_options(a, "hdrcharset=CP437") != ARCHIVE_OK) {
skipping("This system cannot convert character-set"
" from UTF-16 to CP437.");
archive_write_free(a);
return;
}
assertEqualInt(ARCHIVE_OK,
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
/* Set the filename using a UTF-16 string */
archive_entry_copy_pathname_w(entry, L"\u8868.txt");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, entry));
/* The pathname cannot even be represented in the current locale
for inclusion in the error message. */
assertEqualString("Can't translate pathname to CP437",
archive_error_string(a));
archive_entry_free(entry);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
#endif
}
@@ -7,12 +7,15 @@
* All rights reserved. * All rights reserved.
*/ */
#include "bsdunzip_platform.h" #include "lafe_platform.h"
#ifndef HAVE_GETLINE #ifndef HAVE_GETLINE
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
#include <stdlib.h> #include <stdlib.h>
#endif #endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#ifdef HAVE_STDIO_H #ifdef HAVE_STDIO_H
#include <stdio.h> #include <stdio.h>
#endif #endif
@@ -26,8 +29,10 @@
#include <string.h> #include <string.h>
#endif #endif
#include "lafe_getline.h"
static ssize_t static ssize_t
la_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) lafe_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
{ {
char *ptr, *eptr; char *ptr, *eptr;
@@ -72,6 +77,6 @@ la_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
ssize_t ssize_t
getline(char **buf, size_t *bufsiz, FILE *fp) getline(char **buf, size_t *bufsiz, FILE *fp)
{ {
return la_getdelim(buf, bufsiz, '\n', fp); return lafe_getdelim(buf, bufsiz, '\n', fp);
} }
#endif #endif
@@ -5,12 +5,19 @@
* All rights reserved. * All rights reserved.
*/ */
#ifndef LA_GETLINE_H_INCLUDED #ifndef LAFE_GETLINE_H_INCLUDED
#define LA_GETLINE_H_INCLUDED #define LAFE_GETLINE_H_INCLUDED
#include "lafe_platform.h"
#include <stdio.h>
#ifndef HAVE_GETLINE #ifndef HAVE_GETLINE
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
ssize_t getline(char **buf, size_t *bufsiz, FILE *fp); ssize_t getline(char **buf, size_t *bufsiz, FILE *fp);
#endif #endif
#endif /* !LA_GETLINE_H_INCLUDED */ #endif /* !LAFE_GETLINE_H_INCLUDED */
+10 -10
View File
@@ -525,28 +525,28 @@ main(int argc, char **argv)
if (archive_match_include_date(bsdtar->matching, if (archive_match_include_date(bsdtar->matching,
ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER,
bsdtar->argument) != ARCHIVE_OK) bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(bsdtar->matching)); archive_error_string(bsdtar->matching));
break; break;
case OPTION_NEWER_CTIME_THAN: case OPTION_NEWER_CTIME_THAN:
if (archive_match_include_file_time(bsdtar->matching, if (archive_match_include_file_time(bsdtar->matching,
ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER,
bsdtar->argument) != ARCHIVE_OK) bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(bsdtar->matching)); archive_error_string(bsdtar->matching));
break; break;
case OPTION_NEWER_MTIME: /* GNU tar */ case OPTION_NEWER_MTIME: /* GNU tar */
if (archive_match_include_date(bsdtar->matching, if (archive_match_include_date(bsdtar->matching,
ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER,
bsdtar->argument) != ARCHIVE_OK) bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(bsdtar->matching)); archive_error_string(bsdtar->matching));
break; break;
case OPTION_NEWER_MTIME_THAN: case OPTION_NEWER_MTIME_THAN:
if (archive_match_include_file_time(bsdtar->matching, if (archive_match_include_file_time(bsdtar->matching,
ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER,
bsdtar->argument) != ARCHIVE_OK) bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(bsdtar->matching)); archive_error_string(bsdtar->matching));
break; break;
case OPTION_NODUMP: /* star */ case OPTION_NODUMP: /* star */
@@ -618,28 +618,28 @@ main(int argc, char **argv)
if (archive_match_include_date(bsdtar->matching, if (archive_match_include_date(bsdtar->matching,
ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER,
bsdtar->argument) != ARCHIVE_OK) bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(bsdtar->matching)); archive_error_string(bsdtar->matching));
break; break;
case OPTION_OLDER_CTIME_THAN: case OPTION_OLDER_CTIME_THAN:
if (archive_match_include_file_time(bsdtar->matching, if (archive_match_include_file_time(bsdtar->matching,
ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER,
bsdtar->argument) != ARCHIVE_OK) bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(bsdtar->matching)); archive_error_string(bsdtar->matching));
break; break;
case OPTION_OLDER_MTIME: case OPTION_OLDER_MTIME:
if (archive_match_include_date(bsdtar->matching, if (archive_match_include_date(bsdtar->matching,
ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER,
bsdtar->argument) != ARCHIVE_OK) bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(bsdtar->matching)); archive_error_string(bsdtar->matching));
break; break;
case OPTION_OLDER_MTIME_THAN: case OPTION_OLDER_MTIME_THAN:
if (archive_match_include_file_time(bsdtar->matching, if (archive_match_include_file_time(bsdtar->matching,
ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER,
bsdtar->argument) != ARCHIVE_OK) bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(bsdtar->matching)); archive_error_string(bsdtar->matching));
break; break;
case OPTION_ONE_FILE_SYSTEM: /* GNU tar */ case OPTION_ONE_FILE_SYSTEM: /* GNU tar */
@@ -819,7 +819,7 @@ main(int argc, char **argv)
if (archive_match_exclude_pattern_from_file( if (archive_match_exclude_pattern_from_file(
bsdtar->matching, bsdtar->argument, 0) bsdtar->matching, bsdtar->argument, 0)
!= ARCHIVE_OK) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(bsdtar->matching)); archive_error_string(bsdtar->matching));
break; break;
case 'x': /* SUSv2 */ case 'x': /* SUSv2 */
@@ -1026,7 +1026,7 @@ main(int argc, char **argv)
if (bsdtar->return_value != 0) if (bsdtar->return_value != 0)
lafe_warnc(0, lafe_warnc(0,
"Error exit delayed from previous errors."); "Error exit delayed from previous errors");
return (bsdtar->return_value); return (bsdtar->return_value);
} }
+1 -1
View File
@@ -255,7 +255,7 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
break; break;
p = archive_entry_pathname(entry); p = archive_entry_pathname(entry);
if (p == NULL || p[0] == '\0') { if (p == NULL || p[0] == '\0') {
lafe_warnc(0, "Archive entry has empty or unreadable filename ... skipping."); lafe_warnc(0, "Archive entry has empty or unreadable filename ... skipping");
bsdtar->return_value = 1; bsdtar->return_value = 1;
continue; continue;
} }
+4 -4
View File
@@ -715,8 +715,8 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
/* Use uname if it's present, else uid. */ /* Use uname if it's present, else uid. */
p = archive_entry_uname(entry); p = archive_entry_uname(entry);
if ((p == NULL) || (*p == '\0')) { if ((p == NULL) || (*p == '\0')) {
snprintf(tmp, sizeof(tmp), "%lu ", snprintf(tmp, sizeof(tmp), "%lld ",
(unsigned long)archive_entry_uid(entry)); (long long)archive_entry_uid(entry));
p = tmp; p = tmp;
} }
w = strlen(p); w = strlen(p);
@@ -730,8 +730,8 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
fprintf(out, "%s", p); fprintf(out, "%s", p);
w = strlen(p); w = strlen(p);
} else { } else {
snprintf(tmp, sizeof(tmp), "%lu", snprintf(tmp, sizeof(tmp), "%lld",
(unsigned long)archive_entry_gid(entry)); (long long)archive_entry_gid(entry));
w = strlen(tmp); w = strlen(tmp);
fprintf(out, "%s", tmp); fprintf(out, "%s", tmp);
} }
+8 -8
View File
@@ -301,7 +301,7 @@ tar_mode_r(struct bsdtar *bsdtar)
archive_read_free(a); archive_read_free(a);
close(bsdtar->fd); close(bsdtar->fd);
lafe_errc(1, 0, lafe_errc(1, 0,
"Cannot append to compressed archive."); "Cannot append to compressed archive");
} }
/* Keep going until we hit end-of-archive */ /* Keep going until we hit end-of-archive */
format = archive_format(a); format = archive_format(a);
@@ -329,7 +329,7 @@ tar_mode_r(struct bsdtar *bsdtar)
if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK) if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK)
&& format != ARCHIVE_FORMAT_EMPTY) { && format != ARCHIVE_FORMAT_EMPTY) {
lafe_errc(1, 0, lafe_errc(1, 0,
"Format %s is incompatible with the archive %s.", "Format %s is incompatible with the archive %s",
cset_get_format(bsdtar->cset), bsdtar->filename); cset_get_format(bsdtar->cset), bsdtar->filename);
} }
} else { } else {
@@ -394,12 +394,12 @@ tar_mode_u(struct bsdtar *bsdtar)
archive_read_free(a); archive_read_free(a);
close(bsdtar->fd); close(bsdtar->fd);
lafe_errc(1, 0, lafe_errc(1, 0,
"Cannot append to compressed archive."); "Cannot append to compressed archive");
} }
if (archive_match_exclude_entry(bsdtar->matching, if (archive_match_exclude_entry(bsdtar->matching,
ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER | ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER |
ARCHIVE_MATCH_EQUAL, entry) != ARCHIVE_OK) ARCHIVE_MATCH_EQUAL, entry) != ARCHIVE_OK)
lafe_errc(1, 0, "Error : %s", lafe_errc(1, 0, "%s",
archive_error_string(bsdtar->matching)); archive_error_string(bsdtar->matching));
/* Record the last format determination we see */ /* Record the last format determination we see */
format = archive_format(a); format = archive_format(a);
@@ -786,7 +786,7 @@ copy_file_data_block(struct bsdtar *bsdtar, struct archive *a,
* continue. */ * continue. */
lafe_warnc(0, lafe_warnc(0,
"%s: Truncated write; file may " "%s: Truncated write; file may "
"have grown while being archived.", "have grown while being archived",
archive_entry_pathname(entry)); archive_entry_pathname(entry));
return (0); return (0);
} }
@@ -805,7 +805,7 @@ copy_file_data_block(struct bsdtar *bsdtar, struct archive *a,
/* Write was truncated; warn but continue. */ /* Write was truncated; warn but continue. */
lafe_warnc(0, lafe_warnc(0,
"%s: Truncated write; file may have grown " "%s: Truncated write; file may have grown "
"while being archived.", "while being archived",
archive_entry_pathname(entry)); archive_entry_pathname(entry));
return (0); return (0);
} }
@@ -1052,14 +1052,14 @@ test_for_append(struct bsdtar *bsdtar)
if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL) if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
lafe_errc(1, 0, "no files or directories specified"); lafe_errc(1, 0, "no files or directories specified");
if (bsdtar->filename == NULL) if (bsdtar->filename == NULL)
lafe_errc(1, 0, "Cannot append to stdout."); lafe_errc(1, 0, "Cannot append to stdout");
if (stat(bsdtar->filename, &s) != 0) if (stat(bsdtar->filename, &s) != 0)
return; return;
if (!S_ISREG(s.st_mode) && !S_ISBLK(s.st_mode)) if (!S_ISREG(s.st_mode) && !S_ISBLK(s.st_mode))
lafe_errc(1, 0, lafe_errc(1, 0,
"Cannot append to %s: not a regular file.", "Cannot append to %s: not a regular file",
bsdtar->filename); bsdtar->filename);
/* Is this an appropriate check here on Windows? */ /* Is this an appropriate check here on Windows? */
@@ -163,6 +163,9 @@
/* change file/directory permissions and errors if it fails */ /* change file/directory permissions and errors if it fails */
#define assertChmod(pathname, mode) \ #define assertChmod(pathname, mode) \
assertion_chmod(__FILE__, __LINE__, pathname, mode) assertion_chmod(__FILE__, __LINE__, pathname, mode)
/* change file/directory ownership and errors if it fails */
#define assertChown(pathname, user, group) \
assertion_chown(__FILE__, __LINE__, pathname, user, group)
/* Assert two files have the same file flags */ /* Assert two files have the same file flags */
#define assertEqualFflags(patha, pathb) \ #define assertEqualFflags(patha, pathb) \
assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 0) assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 0)
@@ -279,6 +282,7 @@ void failure(const char *fmt, ...) __LA_PRINTFLIKE(1, 2);
int assertion_assert(const char *, int, int, const char *, void *); int assertion_assert(const char *, int, int, const char *, void *);
int assertion_chdir(const char *, int, const char *); int assertion_chdir(const char *, int, const char *);
int assertion_chmod(const char *, int, const char *, int); int assertion_chmod(const char *, int, const char *, int);
int assertion_chown(const char *, int, const char *, int, int);
int assertion_compare_fflags(const char *, int, const char *, const char *, int assertion_compare_fflags(const char *, int, const char *, const char *,
int); int);
int assertion_empty_file(const char *, int, const char *); int assertion_empty_file(const char *, int, const char *);
+83 -2
View File
@@ -96,6 +96,12 @@ extern char **environ;
# define USE_POSIX_SPAWN 1 # define USE_POSIX_SPAWN 1
# endif # endif
#endif #endif
#if !defined(_WIN32)
# if HAVE_PWD_H && HAVE_GETEUID && HAVE_GETEGID
# include <pwd.h>
# define RUN_TEST_UNPRIV 1
# endif
#endif
#ifndef nitems #ifndef nitems
#define nitems(arr) (sizeof(arr) / sizeof((arr)[0])) #define nitems(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -179,6 +185,14 @@ const char *testprogfile;
const char *testprog; const char *testprog;
#endif #endif
#ifdef RUN_TEST_UNPRIV
/* Unprivileged user to run as */
const char *tuser = "nobody";
/* Original and test credentials */
uid_t ouid, tuid;
uid_t ogid, tgid;
#endif
#if defined(_WIN32) && !defined(__CYGWIN__) #if defined(_WIN32) && !defined(__CYGWIN__)
static void *GetFunctionKernel32(const char *); static void *GetFunctionKernel32(const char *);
static int my_CreateSymbolicLinkA(const char *, const char *, int); static int my_CreateSymbolicLinkA(const char *, const char *, int);
@@ -632,6 +646,22 @@ assertion_chmod(const char *file, int line, const char *pathname, int mode)
} }
/* change file/directory ownership and errors if it fails */
int
assertion_chown(const char *file, int line, const char *pathname, int user,
int group)
{
assertion_count(file, line);
#ifdef HAVE_CHOWN
if (chown(pathname, (uid_t)user, (gid_t)group) == 0)
return (1);
#endif
failure_start(file, line, "chown(\"%s\", %d, %d)", pathname,
user, group);
failure_finish(NULL);
return (0);
}
/* Verify two integers are equal. */ /* Verify two integers are equal. */
int int
assertion_equal_int(const char *file, int line, assertion_equal_int(const char *file, int line,
@@ -3610,8 +3640,11 @@ test_run(int i, const char *tmpdir)
exit(1); exit(1);
} }
testworkdir = workdir; testworkdir = workdir;
if (!assertMakeDir(testworkdir, 0755) if (!assertMakeDir(testworkdir, 0755) ||
|| !assertChdir(testworkdir)) { #ifdef RUN_TEST_UNPRIV
(tuser != NULL && !assertChown(testworkdir, tuid, tgid)) ||
#endif
!assertChdir(testworkdir)) {
fprintf(stderr, fprintf(stderr,
"ERROR: Can't chdir to work dir %s\n", testworkdir); "ERROR: Can't chdir to work dir %s\n", testworkdir);
exit(1); exit(1);
@@ -3620,10 +3653,28 @@ test_run(int i, const char *tmpdir)
set_c_locale(); set_c_locale();
/* Record the umask before we run the test. */ /* Record the umask before we run the test. */
umask(oldumask = umask(0)); umask(oldumask = umask(0));
#ifdef RUN_TEST_UNPRIV
/*
* Temporarily drop privileges.
*/
if (tuser != NULL) {
(void)setegid(tuid);
(void)seteuid(tuid);
}
#endif
/* /*
* Run the actual test. * Run the actual test.
*/ */
(*tests[i].func)(); (*tests[i].func)();
#ifdef RUN_TEST_UNPRIV
/*
* Restore original credentials.
*/
if (tuser != NULL) {
(void)seteuid(ouid);
(void)setegid(ogid);
}
#endif
/* /*
* Clean up and report afterwards. * Clean up and report afterwards.
*/ */
@@ -3949,6 +4000,9 @@ main(int argc, char **argv)
#endif #endif
char *pwd, *testprogdir, *tmp2 = NULL, *vlevel = NULL; char *pwd, *testprogdir, *tmp2 = NULL, *vlevel = NULL;
char tmpdir_timestamp[32]; char tmpdir_timestamp[32];
#ifdef RUN_TEST_UNPRIV
struct passwd *pw;
#endif
(void)argc; /* UNUSED */ (void)argc; /* UNUSED */
@@ -4110,6 +4164,11 @@ main(int argc, char **argv)
case 's': case 's':
fail_if_tests_skipped = 1; fail_if_tests_skipped = 1;
break; break;
#ifdef RUN_TEST_UNPRIV
case 'U':
tuser = optarg;
break;
#endif
case 'u': case 'u':
until_failure++; until_failure++;
break; break;
@@ -4194,6 +4253,28 @@ main(int argc, char **argv)
} }
#endif #endif
#ifdef RUN_TEST_UNPRIV
/*
* Check if we are root, and get user to run as.
*/
ouid = getuid();
ogid = getgid();
if (ouid == 0) {
if ((pw = getpwnam(tuser)) == NULL) {
fprintf(stderr, "ERROR: Unknown user %s\n", tuser);
exit(1);
}
tuid = pw->pw_uid;
tgid = pw->pw_gid;
printf("Will switch to user %s (uid %d gid %d)\n", tuser,
tuid, tgid);
} else {
tuser = NULL;
tuid = ouid;
tgid = ogid;
}
#endif
/* /*
* Create a temp directory for the following tests. * Create a temp directory for the following tests.
* Include the time the tests started as part of the name, * Include the time the tests started as part of the name,
+3 -3
View File
@@ -9,7 +9,7 @@
#include "bsdunzip_platform.h" #include "bsdunzip_platform.h"
#include "la_queue.h" #include "la_queue.h"
#include "la_getline.h" #include "lafe_getline.h"
#ifdef HAVE_SYS_STAT_H #ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
@@ -884,9 +884,9 @@ list(struct archive *a, struct archive_entry *e)
mtime = archive_entry_mtime(e); mtime = archive_entry_mtime(e);
tm = localtime(&mtime); tm = localtime(&mtime);
if (*y_str) if (*y_str)
strftime(buf, sizeof(buf), "%m-%d-%G %R", tm); strftime(buf, sizeof(buf), "%m-%d-%Y %R", tm);
else else
strftime(buf, sizeof(buf), "%m-%d-%g %R", tm); strftime(buf, sizeof(buf), "%m-%d-%y %R", tm);
pathname = archive_entry_pathname(e); pathname = archive_entry_pathname(e);
if (!pathname) if (!pathname)
+13
View File
@@ -131,6 +131,8 @@ TESTS_SRCS= \
test_read_format_ar.c \ test_read_format_ar.c \
test_read_format_cab.c \ test_read_format_cab.c \
test_read_format_cab_filename.c \ test_read_format_cab_filename.c \
test_read_format_cab_lzx_oob.c \
test_read_format_cab_skip_malformed.c \
test_read_format_cpio_afio.c \ test_read_format_cpio_afio.c \
test_read_format_cpio_bin.c \ test_read_format_cpio_bin.c \
test_read_format_cpio_bin_Z.c \ test_read_format_cpio_bin_Z.c \
@@ -159,6 +161,7 @@ TESTS_SRCS= \
test_read_format_iso_Z.c \ test_read_format_iso_Z.c \
test_read_format_iso_multi_extent.c \ test_read_format_iso_multi_extent.c \
test_read_format_iso_xorriso.c \ test_read_format_iso_xorriso.c \
test_read_format_iso_zisofs_overflow.c \
test_read_format_isorr_rr_moved.c \ test_read_format_isorr_rr_moved.c \
test_read_format_isojoliet_bz2.c \ test_read_format_isojoliet_bz2.c \
test_read_format_isojoliet_long.c \ test_read_format_isojoliet_long.c \
@@ -172,10 +175,12 @@ TESTS_SRCS= \
test_read_format_lha_bugfix_0.c \ test_read_format_lha_bugfix_0.c \
test_read_format_lha_filename.c \ test_read_format_lha_filename.c \
test_read_format_lha_filename_utf16.c \ test_read_format_lha_filename_utf16.c \
test_read_format_lha_oversize_header.c \
test_read_format_mtree.c \ test_read_format_mtree.c \
test_read_format_mtree_crash747.c \ test_read_format_mtree_crash747.c \
test_read_format_pax_bz2.c \ test_read_format_pax_bz2.c \
test_read_format_rar.c \ test_read_format_rar.c \
test_read_format_rar5_loop_bug.c \
test_read_format_rar5.c \ test_read_format_rar5.c \
test_read_format_rar_encryption.c \ test_read_format_rar_encryption.c \
test_read_format_rar_encryption_data.c \ test_read_format_rar_encryption_data.c \
@@ -242,6 +247,7 @@ TESTS_SRCS= \
test_sparse_basic.c \ test_sparse_basic.c \
test_tar_filenames.c \ test_tar_filenames.c \
test_tar_large.c \ test_tar_large.c \
test_v7tar_filename_encoding.c \
test_warn_missing_hardlink_target.c \ test_warn_missing_hardlink_target.c \
test_ustar_filenames.c \ test_ustar_filenames.c \
test_ustar_filename_encoding.c \ test_ustar_filename_encoding.c \
@@ -499,8 +505,10 @@ ${PACKAGE}FILES+= test_read_format_7zip_lzma2_riscv.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_lzma2_sparc.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_lzma2_sparc.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_malformed.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_malformed.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_malformed2.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_malformed2.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_malformed3.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_packinfo_digests.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_packinfo_digests.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_ppmd.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_ppmd.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_sfx_elf64trunc.elf.uu
${PACKAGE}FILES+= test_read_format_7zip_sfx_elf.elf.uu ${PACKAGE}FILES+= test_read_format_7zip_sfx_elf.elf.uu
${PACKAGE}FILES+= test_read_format_7zip_sfx_modified_pe.exe.uu ${PACKAGE}FILES+= test_read_format_7zip_sfx_modified_pe.exe.uu
${PACKAGE}FILES+= test_read_format_7zip_sfx_pe.exe.uu ${PACKAGE}FILES+= test_read_format_7zip_sfx_pe.exe.uu
@@ -517,6 +525,8 @@ ${PACKAGE}FILES+= test_read_format_cab_1.cab.uu
${PACKAGE}FILES+= test_read_format_cab_2.cab.uu ${PACKAGE}FILES+= test_read_format_cab_2.cab.uu
${PACKAGE}FILES+= test_read_format_cab_3.cab.uu ${PACKAGE}FILES+= test_read_format_cab_3.cab.uu
${PACKAGE}FILES+= test_read_format_cab_filename_cp932.cab.uu ${PACKAGE}FILES+= test_read_format_cab_filename_cp932.cab.uu
${PACKAGE}FILES+= test_read_format_cab_lzx_oob.cab.uu
${PACKAGE}FILES+= test_read_format_cab_skip_malformed.cab.uu
${PACKAGE}FILES+= test_read_format_cpio_bin_be.cpio.uu ${PACKAGE}FILES+= test_read_format_cpio_bin_be.cpio.uu
${PACKAGE}FILES+= test_read_format_cpio_bin_le.cpio.uu ${PACKAGE}FILES+= test_read_format_cpio_bin_le.cpio.uu
${PACKAGE}FILES+= test_read_format_cpio_filename_cp866.cpio.uu ${PACKAGE}FILES+= test_read_format_cpio_filename_cp866.cpio.uu
@@ -552,6 +562,7 @@ ${PACKAGE}FILES+= test_read_format_iso_rockridge_ce.iso.Z.uu
${PACKAGE}FILES+= test_read_format_iso_rockridge_new.iso.Z.uu ${PACKAGE}FILES+= test_read_format_iso_rockridge_new.iso.Z.uu
${PACKAGE}FILES+= test_read_format_iso_rockridge_rr_moved.iso.Z.uu ${PACKAGE}FILES+= test_read_format_iso_rockridge_rr_moved.iso.Z.uu
${PACKAGE}FILES+= test_read_format_iso_xorriso.iso.Z.uu ${PACKAGE}FILES+= test_read_format_iso_xorriso.iso.Z.uu
${PACKAGE}FILES+= test_read_format_iso_zisofs_overflow.iso.uu
${PACKAGE}FILES+= test_read_format_iso_zisofs.iso.Z.uu ${PACKAGE}FILES+= test_read_format_iso_zisofs.iso.Z.uu
${PACKAGE}FILES+= test_read_format_lha_bugfix_0.lzh.uu ${PACKAGE}FILES+= test_read_format_lha_bugfix_0.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_filename_cp932.lzh.uu ${PACKAGE}FILES+= test_read_format_lha_filename_cp932.lzh.uu
@@ -563,6 +574,7 @@ ${PACKAGE}FILES+= test_read_format_lha_header3.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_lh0.lzh.uu ${PACKAGE}FILES+= test_read_format_lha_lh0.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_lh6.lzh.uu ${PACKAGE}FILES+= test_read_format_lha_lh6.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_lh7.lzh.uu ${PACKAGE}FILES+= test_read_format_lha_lh7.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_oversize_header.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_withjunk.lzh.uu ${PACKAGE}FILES+= test_read_format_lha_withjunk.lzh.uu
${PACKAGE}FILES+= test_read_format_mtree.mtree.uu ${PACKAGE}FILES+= test_read_format_mtree.mtree.uu
${PACKAGE}FILES+= test_read_format_mtree_crash747.mtree.bz2.uu ${PACKAGE}FILES+= test_read_format_mtree_crash747.mtree.bz2.uu
@@ -615,6 +627,7 @@ ${PACKAGE}FILES+= test_read_format_rar5_dirdata.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_distance_overflow.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_distance_overflow.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_encrypted.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_encrypted.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_encrypted_filenames.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_encrypted_filenames.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_loop_bug.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_solid_encrypted.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_solid_encrypted.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_solid_encrypted_filenames.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_solid_encrypted_filenames.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_extra_field_version.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_extra_field_version.rar.uu
+1 -1
View File
@@ -12,7 +12,7 @@ BSDUNZIP_VERSION_STRING!= sed -n '/define.*ARCHIVE_VERSION_ONLY_STRING/{s,[^0-9.
SRCS= bsdunzip.c SRCS= bsdunzip.c
.PATH: ${_LIBARCHIVEDIR}/libarchive_fe .PATH: ${_LIBARCHIVEDIR}/libarchive_fe
SRCS+= cmdline.c lafe_err.c passphrase.c SRCS+= cmdline.c lafe_err.c lafe_getline.c passphrase.c
CFLAGS+= -DBSDUNZIP_VERSION_STRING=\"${BSDUNZIP_VERSION_STRING}\" CFLAGS+= -DBSDUNZIP_VERSION_STRING=\"${BSDUNZIP_VERSION_STRING}\"
CFLAGS+= -DPLATFORM_CONFIG_H=\"${_LIBARCHIVECONFDIR}/config_freebsd.h\" CFLAGS+= -DPLATFORM_CONFIG_H=\"${_LIBARCHIVECONFDIR}/config_freebsd.h\"