mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[cmp] update Bled to latest
* Also try to fix the fallthrough Coverity warning in format_ext.c
This commit is contained in:
parent
2cf183e9f1
commit
07d1fdcc2f
15 changed files with 485 additions and 267 deletions
|
@ -64,6 +64,9 @@ typedef struct archive_handle_t {
|
|||
/* Currently processed file's header */
|
||||
file_header_t *file_header;
|
||||
|
||||
/* List of link placeholders */
|
||||
llist_t *link_placeholders;
|
||||
|
||||
/* Process the header component, e.g. tar -t */
|
||||
void FAST_FUNC (*action_header)(const file_header_t *);
|
||||
|
||||
|
@ -77,6 +80,9 @@ typedef struct archive_handle_t {
|
|||
off_t offset;
|
||||
|
||||
/* Archiver specific. Can make it a union if it ever gets big */
|
||||
#if ENABLE_FEATURE_TAR_LONG_OPTIONS
|
||||
unsigned tar__strip_components;
|
||||
#endif
|
||||
#define PAX_NEXT_FILE 0
|
||||
#define PAX_GLOBAL 1
|
||||
#if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB
|
||||
|
@ -95,6 +101,7 @@ typedef struct archive_handle_t {
|
|||
#endif
|
||||
#if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM
|
||||
uoff_t cpio__blocks;
|
||||
struct bb_uidgid_t cpio__owner;
|
||||
struct hardlinks_t *cpio__hardlinks_to_create;
|
||||
struct hardlinks_t *cpio__created_hardlinks;
|
||||
#endif
|
||||
|
@ -110,20 +117,23 @@ typedef struct archive_handle_t {
|
|||
const char *ar__name;
|
||||
struct archive_handle_t *ar__out;
|
||||
#endif
|
||||
#if ENABLE_FEATURE_AR_LONG_FILENAMES
|
||||
char *ar__long_names;
|
||||
unsigned ar__long_name_size;
|
||||
#endif
|
||||
} archive_handle_t;
|
||||
/* bits in ah_flags */
|
||||
#define ARCHIVE_RESTORE_DATE (1 << 0)
|
||||
#define ARCHIVE_CREATE_LEADING_DIRS (1 << 1)
|
||||
#define ARCHIVE_UNLINK_OLD (1 << 2)
|
||||
#define ARCHIVE_EXTRACT_QUIET (1 << 3)
|
||||
#define ARCHIVE_EXTRACT_NEWER (1 << 4)
|
||||
#define ARCHIVE_DONT_RESTORE_OWNER (1 << 5)
|
||||
#define ARCHIVE_DONT_RESTORE_PERM (1 << 6)
|
||||
#define ARCHIVE_NUMERIC_OWNER (1 << 7)
|
||||
#define ARCHIVE_O_TRUNC (1 << 8)
|
||||
#define ARCHIVE_REMEMBER_NAMES (1 << 9)
|
||||
#define ARCHIVE_EXTRACT_NEWER (1 << 3)
|
||||
#define ARCHIVE_DONT_RESTORE_OWNER (1 << 4)
|
||||
#define ARCHIVE_DONT_RESTORE_PERM (1 << 5)
|
||||
#define ARCHIVE_NUMERIC_OWNER (1 << 6)
|
||||
#define ARCHIVE_O_TRUNC (1 << 7)
|
||||
#define ARCHIVE_REMEMBER_NAMES (1 << 8)
|
||||
#if ENABLE_RPM
|
||||
#define ARCHIVE_REPLACE_VIA_RENAME (1 << 10)
|
||||
#define ARCHIVE_REPLACE_VIA_RENAME (1 << 9)
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -157,6 +167,11 @@ typedef struct tar_header_t { /* byte offset */
|
|||
struct BUG_tar_header {
|
||||
char c[sizeof(tar_header_t) == TAR_BLOCK_SIZE ? 1 : -1];
|
||||
};
|
||||
void chksum_and_xwrite_tar_header(int fd, struct tar_header_t *hp) FAST_FUNC;
|
||||
|
||||
|
||||
extern const char cpio_TRAILER[];
|
||||
|
||||
|
||||
archive_handle_t *init_handle(void) FAST_FUNC;
|
||||
|
||||
|
@ -188,22 +203,22 @@ void seek_by_jump(int fd, off_t amount) FAST_FUNC;
|
|||
void seek_by_read(int fd, off_t amount) FAST_FUNC;
|
||||
|
||||
const char *strip_unsafe_prefix(const char *str) FAST_FUNC;
|
||||
void create_or_remember_link(llist_t **link_placeholders,
|
||||
const char *target,
|
||||
const char *linkname,
|
||||
int hard_link) FAST_FUNC;
|
||||
void create_links_from_list(llist_t *list) FAST_FUNC;
|
||||
|
||||
void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC;
|
||||
const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC;
|
||||
const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC;
|
||||
|
||||
/* A bit of bunzip2 internals are exposed for compressed help support: */
|
||||
typedef struct bunzip_data bunzip_data;
|
||||
int start_bunzip(bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC;
|
||||
/* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes
|
||||
* in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */
|
||||
int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC;
|
||||
void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;
|
||||
char *unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) FAST_FUNC;
|
||||
|
||||
/* Meaning and direction (input/output) of the fields are transformer-specific */
|
||||
typedef struct transformer_state_t {
|
||||
int8_t check_signature; /* most often referenced member */
|
||||
int8_t signature_skipped; /* most often referenced member */
|
||||
|
||||
IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate);
|
||||
USE_FOR_NOMMU(const char *xformer_prog;)
|
||||
|
@ -223,6 +238,12 @@ typedef struct transformer_state_t {
|
|||
uint64_t bytes_in; /* used in unzip code only: needs to know packed size */
|
||||
uint32_t crc32;
|
||||
time_t mtime; /* gunzip code may set this on exit */
|
||||
|
||||
union { /* if we read magic, it's saved here */
|
||||
uint8_t b[8];
|
||||
uint16_t b16[4];
|
||||
uint32_t b32[2];
|
||||
} magic;
|
||||
} transformer_state_t;
|
||||
|
||||
void init_transformer_state(transformer_state_t *xstate) FAST_FUNC;
|
||||
|
@ -278,11 +299,11 @@ int bbunpack(char **argv,
|
|||
void check_errors_in_children(int signo);
|
||||
#if BB_MMU
|
||||
void fork_transformer(int fd,
|
||||
int check_signature,
|
||||
int signature_skipped,
|
||||
IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
|
||||
) FAST_FUNC;
|
||||
#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (transformer))
|
||||
#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 0, (transformer))
|
||||
#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 0, (transformer))
|
||||
#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 1, (transformer))
|
||||
#else
|
||||
void fork_transformer(int fd, const char *transform_prog) FAST_FUNC;
|
||||
#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog))
|
||||
|
|
|
@ -65,7 +65,6 @@ int64_t bled_uncompress(const char* src, const char* dst, int type)
|
|||
init_transformer_state(&xstate);
|
||||
xstate.src_fd = -1;
|
||||
xstate.dst_fd = -1;
|
||||
xstate.check_signature = 1;
|
||||
|
||||
xstate.src_fd = _openU(src, _O_RDONLY | _O_BINARY, 0);
|
||||
if (xstate.src_fd < 0) {
|
||||
|
@ -113,7 +112,6 @@ int64_t bled_uncompress_with_handles(HANDLE hSrc, HANDLE hDst, int type)
|
|||
init_transformer_state(&xstate);
|
||||
xstate.src_fd = -1;
|
||||
xstate.dst_fd = -1;
|
||||
xstate.check_signature = 1;
|
||||
|
||||
xstate.src_fd = _open_osfhandle((intptr_t)hSrc, _O_RDONLY);
|
||||
if (xstate.src_fd < 0) {
|
||||
|
@ -157,7 +155,6 @@ int64_t bled_uncompress_to_buffer(const char* src, char* buf, size_t size, int t
|
|||
init_transformer_state(&xstate);
|
||||
xstate.src_fd = -1;
|
||||
xstate.dst_fd = -1;
|
||||
xstate.check_signature = 1;
|
||||
|
||||
if (src[0] == 0) {
|
||||
xstate.src_fd = bb_virtual_fd;
|
||||
|
@ -206,7 +203,6 @@ int64_t bled_uncompress_to_dir(const char* src, const char* dir, int type)
|
|||
init_transformer_state(&xstate);
|
||||
xstate.src_fd = -1;
|
||||
xstate.dst_fd = -1;
|
||||
xstate.check_signature = 1;
|
||||
|
||||
xstate.src_fd = _openU(src, _O_RDONLY | _O_BINARY, 0);
|
||||
if (xstate.src_fd < 0) {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
/*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||
*/
|
||||
|
||||
#include "libbb.h"
|
||||
#include "bb_archive.h"
|
||||
|
||||
|
@ -11,6 +10,12 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
|
|||
file_header_t *file_header = archive_handle->file_header;
|
||||
int dst_fd;
|
||||
int res;
|
||||
char *hard_link;
|
||||
#if ENABLE_FEATURE_TAR_LONG_OPTIONS
|
||||
char *dst_name;
|
||||
#else
|
||||
# define dst_name (file_header->name)
|
||||
#endif
|
||||
|
||||
#if ENABLE_FEATURE_TAR_SELINUX
|
||||
char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
|
||||
|
@ -23,11 +28,49 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Hard links are encoded as regular files of size 0
|
||||
* with a nonempty link field */
|
||||
hard_link = NULL;
|
||||
if (S_ISREG(file_header->mode) && file_header->size == 0)
|
||||
hard_link = file_header->link_target;
|
||||
|
||||
#if ENABLE_FEATURE_TAR_LONG_OPTIONS
|
||||
dst_name = file_header->name;
|
||||
if (archive_handle->tar__strip_components) {
|
||||
unsigned n = archive_handle->tar__strip_components;
|
||||
do {
|
||||
dst_name = strchr(dst_name, '/');
|
||||
if (!dst_name || dst_name[1] == '\0') {
|
||||
data_skip(archive_handle);
|
||||
goto ret;
|
||||
}
|
||||
dst_name++;
|
||||
/*
|
||||
* Link target is shortened only for hardlinks:
|
||||
* softlinks restored unchanged.
|
||||
*/
|
||||
if (hard_link) {
|
||||
// GNU tar 1.26 does not check that we reached end of link name:
|
||||
// if "dir/hardlink" is hardlinked to "file",
|
||||
// tar xvf a.tar --strip-components=1 says:
|
||||
// tar: hardlink: Cannot hard link to '': No such file or directory
|
||||
// and continues processing. We silently skip such entries.
|
||||
hard_link = strchr(hard_link, '/');
|
||||
if (!hard_link || hard_link[1] == '\0') {
|
||||
data_skip(archive_handle);
|
||||
goto ret;
|
||||
}
|
||||
hard_link++;
|
||||
}
|
||||
} while (--n != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
|
||||
char *slash = strrchr(file_header->name, '/');
|
||||
char *slash = strrchr(dst_name, '/');
|
||||
if (slash) {
|
||||
*slash = '\0';
|
||||
bb_make_directory(file_header->name, -1, FILEUTILS_RECUR);
|
||||
bb_make_directory(dst_name, -1, FILEUTILS_RECUR);
|
||||
*slash = '/';
|
||||
}
|
||||
}
|
||||
|
@ -35,12 +78,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
|
|||
if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
|
||||
/* Remove the entry if it exists */
|
||||
if (!S_ISDIR(file_header->mode)) {
|
||||
/* Is it hardlink?
|
||||
* We encode hard links as regular files of size 0 with a symlink */
|
||||
if (S_ISREG(file_header->mode)
|
||||
&& file_header->link_target
|
||||
&& file_header->size == 0
|
||||
) {
|
||||
if (hard_link) {
|
||||
/* Ugly special case:
|
||||
* tar cf t.tar hardlink1 hardlink2 hardlink1
|
||||
* results in this tarball structure:
|
||||
|
@ -48,56 +86,46 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
|
|||
* hardlink2 -> hardlink1
|
||||
* hardlink1 -> hardlink1 <== !!!
|
||||
*/
|
||||
if (strcmp(file_header->link_target, file_header->name) == 0)
|
||||
if (strcmp(hard_link, dst_name) == 0)
|
||||
goto ret;
|
||||
}
|
||||
/* Proceed with deleting */
|
||||
if (_unlink(file_header->name) == -1
|
||||
if (_unlink(dst_name) == -1
|
||||
&& errno != ENOENT
|
||||
) {
|
||||
bb_perror_msg_and_die("can't remove old file %s",
|
||||
file_header->name);
|
||||
dst_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
|
||||
/* Remove the existing entry if its older than the extracted entry */
|
||||
struct stat existing_sb;
|
||||
if (lstat(file_header->name, &existing_sb) == -1) {
|
||||
if (lstat(dst_name, &existing_sb) == -1) {
|
||||
if (errno != ENOENT) {
|
||||
bb_perror_msg_and_die("can't stat old file");
|
||||
bb_simple_perror_msg_and_die("can't stat old file");
|
||||
}
|
||||
}
|
||||
else if (existing_sb.st_mtime >= file_header->mtime) {
|
||||
if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
|
||||
&& !S_ISDIR(file_header->mode)
|
||||
) {
|
||||
if (!S_ISDIR(file_header->mode)) {
|
||||
bb_error_msg("%s not created: newer or "
|
||||
"same age file exists", file_header->name);
|
||||
"same age file exists", dst_name);
|
||||
}
|
||||
data_skip(archive_handle);
|
||||
goto ret;
|
||||
}
|
||||
else if ((_unlink(file_header->name) == -1) && (errno != EISDIR)) {
|
||||
else if ((_unlink(dst_name) == -1) && (errno != EISDIR)) {
|
||||
bb_perror_msg_and_die("can't remove old file %s",
|
||||
file_header->name);
|
||||
dst_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle hard links separately
|
||||
* We encode hard links as regular files of size 0 with a symlink */
|
||||
if (S_ISREG(file_header->mode)
|
||||
&& file_header->link_target
|
||||
&& file_header->size == 0
|
||||
) {
|
||||
/* hard link */
|
||||
res = link(file_header->link_target, file_header->name);
|
||||
if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
|
||||
bb_perror_msg("can't create %slink "
|
||||
"from %s to %s", "hard",
|
||||
file_header->name,
|
||||
file_header->link_target);
|
||||
}
|
||||
/* Handle hard links separately */
|
||||
if (hard_link) {
|
||||
create_or_remember_link(&archive_handle->link_placeholders,
|
||||
hard_link,
|
||||
dst_name,
|
||||
1);
|
||||
/* Hardlinks have no separate mode/ownership, skip chown/chmod */
|
||||
goto ret;
|
||||
}
|
||||
|
@ -106,15 +134,17 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
|
|||
switch (file_header->mode & S_IFMT) {
|
||||
case S_IFREG: {
|
||||
/* Regular file */
|
||||
char *dst_name;
|
||||
#ifdef ARCHIVE_REPLACE_VIA_RENAME
|
||||
char *dst_nameN;
|
||||
#endif
|
||||
int flags = O_WRONLY | O_CREAT | O_EXCL;
|
||||
if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
dst_name = file_header->name;
|
||||
#ifdef ARCHIVE_REPLACE_VIA_RENAME
|
||||
dst_nameN = dst_name;
|
||||
if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME)
|
||||
/* rpm-style temp file name */
|
||||
dst_name = xasprintf("%s;%x", dst_name, (int)getpid());
|
||||
dst_nameN = xasprintf("%s;%x", dst_name, (int)getpid());
|
||||
#endif
|
||||
if (_sopen_s(&dst_fd, dst_name, flags, _SH_DENYNO, file_header->mode) != 0) {
|
||||
bb_perror_msg_and_die("can't open file %s", dst_name);
|
||||
|
@ -123,48 +153,66 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
|
|||
_close(dst_fd);
|
||||
#ifdef ARCHIVE_REPLACE_VIA_RENAME
|
||||
if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) {
|
||||
xrename(dst_name, file_header->name);
|
||||
free(dst_name);
|
||||
xrename(dst_nameN, dst_name);
|
||||
free(dst_nameN);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case S_IFDIR:
|
||||
res = mkdir(file_header->name, file_header->mode);
|
||||
if ((res == -1)
|
||||
//TODO: this causes problems if tarball contains a r-xr-xr-x directory:
|
||||
// we create this directory, and then fail to create files inside it
|
||||
// (if tar xf isn't run as root).
|
||||
// GNU tar works around this by chmod-ing directories *after* all files are extracted.
|
||||
res = mkdir(dst_name, file_header->mode);
|
||||
if ((res != 0)
|
||||
&& (errno != EISDIR) /* btw, Linux doesn't return this */
|
||||
&& (errno != EEXIST)
|
||||
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
|
||||
) {
|
||||
bb_perror_msg("can't make dir %s", file_header->name);
|
||||
bb_perror_msg("can't make dir %s", dst_name);
|
||||
}
|
||||
break;
|
||||
case S_IFLNK:
|
||||
/* Symlink */
|
||||
//TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
|
||||
res = symlink(file_header->link_target, file_header->name);
|
||||
if ((res == -1)
|
||||
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
|
||||
) {
|
||||
bb_perror_msg("can't create %slink "
|
||||
"from %s to %s", "sym",
|
||||
file_header->name,
|
||||
file_header->link_target);
|
||||
}
|
||||
|
||||
/* To avoid a directory traversal attack via symlinks,
|
||||
* do not restore symlinks with ".." components
|
||||
* or symlinks starting with "/", unless a magic
|
||||
* envvar is set.
|
||||
*
|
||||
* For example, consider a .tar created via:
|
||||
* $ tar cvf bug.tar anything.txt
|
||||
* $ ln -s /tmp symlink
|
||||
* $ tar --append -f bug.tar symlink
|
||||
* $ rm symlink
|
||||
* $ mkdir symlink
|
||||
* $ tar --append -f bug.tar symlink/evil.py
|
||||
*
|
||||
* This will result in an archive that contains:
|
||||
* $ tar --list -f bug.tar
|
||||
* anything.txt
|
||||
* symlink [-> /tmp]
|
||||
* symlink/evil.py
|
||||
*
|
||||
* Untarring bug.tar would otherwise place evil.py in '/tmp'.
|
||||
*/
|
||||
create_or_remember_link(&archive_handle->link_placeholders,
|
||||
file_header->link_target,
|
||||
dst_name,
|
||||
0);
|
||||
break;
|
||||
case S_IFSOCK:
|
||||
case S_IFBLK:
|
||||
case S_IFCHR:
|
||||
case S_IFIFO:
|
||||
res = mknod(file_header->name, file_header->mode, file_header->device);
|
||||
if ((res == -1)
|
||||
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
|
||||
) {
|
||||
bb_perror_msg("can't create node %s", file_header->name);
|
||||
res = mknod(dst_name, file_header->mode, file_header->device);
|
||||
if (res != 0) {
|
||||
bb_perror_msg("can't create node %s", dst_name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bb_error_msg_and_die("unrecognized file type");
|
||||
bb_simple_error_msg_and_die("unrecognized file type");
|
||||
}
|
||||
|
||||
if (!S_ISLNK(file_header->mode)) {
|
||||
|
@ -199,7 +247,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
|
|||
|
||||
t[1].tv_sec = t[0].tv_sec = file_header->mtime;
|
||||
t[1].tv_usec = t[0].tv_usec = 0;
|
||||
utimes64(file_header->name, t);
|
||||
utimes64(dst_name, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/* vi: set sw=4 ts=4: */
|
||||
/* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net).
|
||||
|
||||
Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
|
||||
which also acknowledges contributions by Mike Burrows, David Wheeler,
|
||||
Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
|
||||
Robert Sedgewick, and Jon L. Bentley.
|
||||
|
||||
Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||
/*
|
||||
* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net).
|
||||
*
|
||||
* Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
|
||||
* which also acknowledges contributions by Mike Burrows, David Wheeler,
|
||||
* Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
|
||||
* Robert Sedgewick, and Jon L. Bentley.
|
||||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||
*/
|
||||
|
||||
/*
|
||||
Size and speed optimizations by Manuel Novoa III (mjn3@codepoet.org).
|
||||
|
||||
|
@ -38,7 +38,6 @@
|
|||
|
||||
Manuel
|
||||
*/
|
||||
|
||||
#include "libbb.h"
|
||||
#include "bb_archive.h"
|
||||
|
||||
|
@ -101,14 +100,14 @@ struct bunzip_data {
|
|||
unsigned dbufSize;
|
||||
|
||||
/* For I/O error handling */
|
||||
jmp_buf jmpbuf;
|
||||
jmp_buf *jmpbuf;
|
||||
|
||||
/* Big things go last (register-relative addressing can be larger for big offsets) */
|
||||
uint32_t crc32Table[256];
|
||||
uint8_t selectors[32768]; /* nSelectors=15 bits */
|
||||
struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */
|
||||
};
|
||||
/* typedef struct bunzip_data bunzip_data; -- done in .h file */
|
||||
typedef struct bunzip_data bunzip_data;
|
||||
|
||||
|
||||
/* Return the next nnn bits of input. All reads from the compressed input
|
||||
|
@ -128,14 +127,15 @@ static unsigned get_bits(bunzip_data *bd, int bits_wanted)
|
|||
/* if "no input fd" case: in_fd == -1, read fails, we jump */
|
||||
bd->inbufCount = safe_read(bd->in_fd, bd->inbuf, IOBUF_SIZE);
|
||||
if (bd->inbufCount <= 0)
|
||||
longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF);
|
||||
longjmp(*bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF);
|
||||
bd->inbufPos = 0;
|
||||
}
|
||||
|
||||
/* Avoid 32-bit overflow (dump bit buffer to top of output) */
|
||||
if (bit_count >= 24) {
|
||||
bits = bd->inbufBits & ((1 << bit_count) - 1);
|
||||
bits = bd->inbufBits & ((1U << bit_count) - 1);
|
||||
bits_wanted -= bit_count;
|
||||
// coverity[negative_shift]
|
||||
bits <<= bits_wanted;
|
||||
bit_count = 0;
|
||||
}
|
||||
|
@ -152,20 +152,20 @@ static unsigned get_bits(bunzip_data *bd, int bits_wanted)
|
|||
|
||||
return bits;
|
||||
}
|
||||
//#define get_bits(bd, n) (dbg("%d:get_bits()", __LINE__), get_bits(bd, n))
|
||||
|
||||
/* Unpacks the next block and sets up for the inverse Burrows-Wheeler step. */
|
||||
static int get_next_block(bunzip_data *bd)
|
||||
{
|
||||
struct group_data *hufGroup;
|
||||
int dbufCount, dbufSize, groupCount, *base, *limit, selector,
|
||||
i, j, t, runPos, symCount, symTotal, nSelectors, byteCount[256];
|
||||
int runCnt;
|
||||
int groupCount, selector,
|
||||
i, j, symCount, symTotal, nSelectors, byteCount[256];
|
||||
uint8_t uc, symToByte[256], mtfSymbol[256], *selectors;
|
||||
uint32_t *dbuf;
|
||||
unsigned origPtr;
|
||||
unsigned origPtr, t;
|
||||
unsigned dbufCount, runPos;
|
||||
unsigned runCnt = 0; // runCnt; /* for compiler */
|
||||
|
||||
dbuf = bd->dbuf;
|
||||
dbufSize = bd->dbufSize;
|
||||
selectors = bd->selectors;
|
||||
|
||||
/* In bbox, we are ok with aborting through setjmp which is set up in start_bunzip */
|
||||
|
@ -180,15 +180,19 @@ static int get_next_block(bunzip_data *bd)
|
|||
i = get_bits(bd, 24);
|
||||
j = get_bits(bd, 24);
|
||||
bd->headerCRC = get_bits(bd, 32);
|
||||
if ((i == 0x177245) && (j == 0x385090)) return RETVAL_LAST_BLOCK;
|
||||
if ((i != 0x314159) || (j != 0x265359)) return RETVAL_NOT_BZIP_DATA;
|
||||
if ((i == 0x177245) && (j == 0x385090))
|
||||
return RETVAL_LAST_BLOCK;
|
||||
if ((i != 0x314159) || (j != 0x265359))
|
||||
return RETVAL_NOT_BZIP_DATA;
|
||||
|
||||
/* We can add support for blockRandomised if anybody complains. There was
|
||||
some code for this in busybox 1.0.0-pre3, but nobody ever noticed that
|
||||
it didn't actually work. */
|
||||
if (get_bits(bd, 1)) return RETVAL_OBSOLETE_INPUT;
|
||||
if (get_bits(bd, 1))
|
||||
return RETVAL_OBSOLETE_INPUT;
|
||||
origPtr = get_bits(bd, 24);
|
||||
if ((int)origPtr > dbufSize) return RETVAL_DATA_ERROR;
|
||||
if (origPtr > bd->dbufSize)
|
||||
return RETVAL_DATA_ERROR;
|
||||
|
||||
/* mapping table: if some byte values are never used (encoding things
|
||||
like ascii text), the compression code removes the gaps to have fewer
|
||||
|
@ -232,8 +236,9 @@ static int get_next_block(bunzip_data *bd)
|
|||
/* Get next value */
|
||||
int n = 0;
|
||||
while (get_bits(bd, 1)) {
|
||||
if (n >= groupCount) return RETVAL_DATA_ERROR;
|
||||
n++;
|
||||
if (n >= groupCount)
|
||||
return RETVAL_DATA_ERROR;
|
||||
}
|
||||
/* Decode MTF to get the next selector */
|
||||
tmp_byte = mtfSymbol[n];
|
||||
|
@ -249,6 +254,8 @@ static int get_next_block(bunzip_data *bd)
|
|||
uint8_t length[MAX_SYMBOLS];
|
||||
/* 8 bits is ALMOST enough for temp[], see below */
|
||||
unsigned temp[MAX_HUFCODE_BITS+1];
|
||||
struct group_data *hufGroup;
|
||||
int *base, *limit;
|
||||
int minLen, maxLen, pp, len_m1;
|
||||
|
||||
/* Read Huffman code lengths for each symbol. They're stored in
|
||||
|
@ -284,8 +291,10 @@ static int get_next_block(bunzip_data *bd)
|
|||
/* Find largest and smallest lengths in this group */
|
||||
minLen = maxLen = length[0];
|
||||
for (i = 1; i < symCount; i++) {
|
||||
if (length[i] > maxLen) maxLen = length[i];
|
||||
else if (length[i] < minLen) minLen = length[i];
|
||||
if (length[i] > maxLen)
|
||||
maxLen = length[i];
|
||||
else if (length[i] < minLen)
|
||||
minLen = length[i];
|
||||
}
|
||||
|
||||
/* Calculate permute[], base[], and limit[] tables from length[].
|
||||
|
@ -308,7 +317,7 @@ static int get_next_block(bunzip_data *bd)
|
|||
base = hufGroup->base - 1;
|
||||
limit = hufGroup->limit - 1;
|
||||
|
||||
/* Calculate permute[]. Concurently, initialize temp[] and limit[]. */
|
||||
/* Calculate permute[]. Concurrently, initialize temp[] and limit[]. */
|
||||
pp = 0;
|
||||
for (i = minLen; i <= maxLen; i++) {
|
||||
int k;
|
||||
|
@ -321,7 +330,8 @@ static int get_next_block(bunzip_data *bd)
|
|||
/* Count symbols coded for at each bit length */
|
||||
/* NB: in pathological cases, temp[8] can end ip being 256.
|
||||
* That's why uint8_t is too small for temp[]. */
|
||||
for (i = 0; i < symCount; i++) temp[length[i]]++;
|
||||
for (i = 0; i < symCount; i++)
|
||||
temp[length[i]]++;
|
||||
|
||||
/* Calculate limit[] (the largest symbol-coding value at each bit
|
||||
* length, which is (previous limit<<1)+symbols at this level), and
|
||||
|
@ -364,12 +374,22 @@ static int get_next_block(bunzip_data *bd)
|
|||
|
||||
runPos = dbufCount = selector = 0;
|
||||
for (;;) {
|
||||
struct group_data *hufGroup;
|
||||
int *base, *limit;
|
||||
int nextSym;
|
||||
uint8_t ngrp;
|
||||
|
||||
/* Fetch next Huffman coding group from list. */
|
||||
symCount = GROUP_SIZE - 1;
|
||||
if (selector >= nSelectors) return RETVAL_DATA_ERROR;
|
||||
hufGroup = bd->groups + selectors[selector++];
|
||||
if (selector >= nSelectors)
|
||||
return RETVAL_DATA_ERROR;
|
||||
ngrp = selectors[selector++];
|
||||
if (ngrp >= groupCount) {
|
||||
dbg("%d selectors[%d]:%d groupCount:%d",
|
||||
__LINE__, selector-1, ngrp, groupCount);
|
||||
return RETVAL_DATA_ERROR;
|
||||
}
|
||||
hufGroup = bd->groups + ngrp;
|
||||
base = hufGroup->base - 1;
|
||||
limit = hufGroup->limit - 1;
|
||||
|
||||
|
@ -404,7 +424,8 @@ static int get_next_block(bunzip_data *bd)
|
|||
}
|
||||
/* Figure how many bits are in next symbol and unget extras */
|
||||
i = hufGroup->minLen;
|
||||
while (nextSym > limit[i]) ++i;
|
||||
while (nextSym > limit[i])
|
||||
++i;
|
||||
j = hufGroup->maxLen - i;
|
||||
if (j < 0)
|
||||
return RETVAL_DATA_ERROR;
|
||||
|
@ -436,7 +457,7 @@ static int get_next_block(bunzip_data *bd)
|
|||
symbols, but a run of length 0 doesn't mean anything in this
|
||||
context). Thus space is saved. */
|
||||
runCnt += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */
|
||||
if (runPos < dbufSize) runPos <<= 1;
|
||||
if (runPos < bd->dbufSize) runPos <<= 1;
|
||||
goto end_of_huffman_loop;
|
||||
}
|
||||
|
||||
|
@ -446,14 +467,15 @@ static int get_next_block(bunzip_data *bd)
|
|||
literal used is the one at the head of the mtfSymbol array.) */
|
||||
if (runPos != 0) {
|
||||
uint8_t tmp_byte;
|
||||
if (dbufCount + runCnt > dbufSize) {
|
||||
dbg("dbufCount:%d+runCnt:%d %d > dbufSize:%d RETVAL_DATA_ERROR",
|
||||
dbufCount, runCnt, dbufCount + runCnt, dbufSize);
|
||||
if (dbufCount + runCnt > bd->dbufSize) {
|
||||
dbg("dbufCount:%u+runCnt:%u %u > dbufSize:%u RETVAL_DATA_ERROR",
|
||||
dbufCount, runCnt, dbufCount + runCnt, bd->dbufSize);
|
||||
return RETVAL_DATA_ERROR;
|
||||
}
|
||||
tmp_byte = symToByte[mtfSymbol[0]];
|
||||
byteCount[tmp_byte] += runCnt;
|
||||
while (--runCnt >= 0) dbuf[dbufCount++] = (uint32_t)tmp_byte;
|
||||
while ((int)--runCnt >= 0)
|
||||
dbuf[dbufCount++] = (uint32_t)tmp_byte;
|
||||
runPos = 0;
|
||||
}
|
||||
|
||||
|
@ -467,7 +489,7 @@ static int get_next_block(bunzip_data *bd)
|
|||
first symbol in the mtf array, position 0, would have been handled
|
||||
as part of a run above. Therefore 1 unused mtf position minus
|
||||
2 non-literal nextSym values equals -1.) */
|
||||
if (dbufCount >= dbufSize) return RETVAL_DATA_ERROR;
|
||||
if (dbufCount >= bd->dbufSize) return RETVAL_DATA_ERROR;
|
||||
i = nextSym - 1;
|
||||
uc = mtfSymbol[i];
|
||||
|
||||
|
@ -507,7 +529,7 @@ static int get_next_block(bunzip_data *bd)
|
|||
}
|
||||
|
||||
/* Figure out what order dbuf would be in if we sorted it. */
|
||||
for (i = 0; i < dbufCount; i++) {
|
||||
for (i = 0; i < (int)dbufCount; i++) {
|
||||
uint8_t tmp_byte = (uint8_t)dbuf[i];
|
||||
int tmp_count = byteCount[tmp_byte];
|
||||
dbuf[tmp_count] |= (i << 8);
|
||||
|
@ -540,7 +562,7 @@ static int get_next_block(bunzip_data *bd)
|
|||
in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0.
|
||||
(Why? This allows to get rid of one local variable)
|
||||
*/
|
||||
int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
|
||||
static int read_bunzip(bunzip_data *bd, char *outbuf, int len)
|
||||
{
|
||||
const uint32_t *dbuf;
|
||||
int pos, current, previous;
|
||||
|
@ -664,7 +686,10 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
|
|||
/* Because bunzip2 is used for help text unpacking, and because bb_show_usage()
|
||||
should work for NOFORK applets too, we must be extremely careful to not leak
|
||||
any allocations! */
|
||||
int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd,
|
||||
static int FAST_FUNC start_bunzip(
|
||||
void *jmpbuf,
|
||||
bunzip_data **bdp,
|
||||
int in_fd,
|
||||
const void *inbuf, int len)
|
||||
{
|
||||
bunzip_data *bd;
|
||||
|
@ -676,13 +701,16 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd,
|
|||
|
||||
/* Figure out how much data to allocate */
|
||||
i = sizeof(bunzip_data);
|
||||
if (in_fd != -1) i += IOBUF_SIZE;
|
||||
if (in_fd != -1)
|
||||
i += IOBUF_SIZE;
|
||||
|
||||
/* Allocate bunzip_data. Most fields initialize to zero. */
|
||||
bd = *bdp = xzalloc(i);
|
||||
if (bd == NULL)
|
||||
return -1;
|
||||
|
||||
bd->jmpbuf = jmpbuf;
|
||||
|
||||
/* Setup input buffer */
|
||||
bd->in_fd = in_fd;
|
||||
if (-1 == in_fd) {
|
||||
|
@ -697,10 +725,6 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd,
|
|||
/* Init the CRC32 table (big endian) */
|
||||
crc32_filltable(bd->crc32Table, 1);
|
||||
|
||||
/* Setup for I/O error handling via longjmp */
|
||||
i = setjmp(bd->jmpbuf);
|
||||
if (i) return i;
|
||||
|
||||
/* Ensure that file starts with "BZh['1'-'9']." */
|
||||
/* Update: now caller verifies 1st two bytes, makes .gz/.bz2
|
||||
* integration easier */
|
||||
|
@ -724,7 +748,7 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd,
|
|||
return RETVAL_OK;
|
||||
}
|
||||
|
||||
void FAST_FUNC dealloc_bunzip(bunzip_data *bd)
|
||||
static void FAST_FUNC dealloc_bunzip(bunzip_data *bd)
|
||||
{
|
||||
free(bd->dbuf);
|
||||
free(bd);
|
||||
|
@ -749,8 +773,12 @@ unpack_bz2_stream(transformer_state_t *xstate)
|
|||
return -1;
|
||||
len = 0;
|
||||
while (1) { /* "Process one BZ... stream" loop */
|
||||
jmp_buf jmpbuf;
|
||||
|
||||
i = start_bunzip(&bd, xstate->src_fd, outbuf + 2, len);
|
||||
/* Setup for I/O error handling via longjmp */
|
||||
i = setjmp(jmpbuf);
|
||||
if (i == 0)
|
||||
i = start_bunzip(&jmpbuf, &bd, xstate->src_fd, outbuf + 2, len);
|
||||
|
||||
if (i == 0) {
|
||||
while (1) { /* "Produce some output bytes" loop */
|
||||
|
@ -781,7 +809,7 @@ unpack_bz2_stream(transformer_state_t *xstate)
|
|||
break;
|
||||
}
|
||||
if (bd->headerCRC != bd->totalCRC) {
|
||||
bb_error_msg("CRC error");
|
||||
bb_simple_error_msg("CRC error");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -811,6 +839,36 @@ unpack_bz2_stream(transformer_state_t *xstate)
|
|||
return i ? i : IF_DESKTOP(total_written) + 0;
|
||||
}
|
||||
|
||||
char* FAST_FUNC
|
||||
unpack_bz2_data(const char *packed, int packed_len, int unpacked_len)
|
||||
{
|
||||
char *outbuf = NULL;
|
||||
bunzip_data *bd;
|
||||
int i;
|
||||
jmp_buf jmpbuf;
|
||||
|
||||
/* Setup for I/O error handling via longjmp */
|
||||
i = setjmp(jmpbuf);
|
||||
if (i == 0) {
|
||||
i = start_bunzip(&jmpbuf,
|
||||
&bd,
|
||||
/* src_fd: */ -1,
|
||||
/* inbuf: */ packed,
|
||||
/* len: */ packed_len
|
||||
);
|
||||
}
|
||||
/* read_bunzip can longjmp and end up here with i != 0
|
||||
* on read data errors! Not trivial */
|
||||
if (i == 0) {
|
||||
/* Cannot use xmalloc: will leak bd in NOFORK case! */
|
||||
outbuf = malloc_or_warn(unpacked_len);
|
||||
if (outbuf)
|
||||
read_bunzip(bd, outbuf, unpacked_len);
|
||||
}
|
||||
dealloc_bunzip(bd);
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
#ifdef TESTING
|
||||
|
||||
static char *const bunzip_errors[] = {
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
#include "libbb.h"
|
||||
#include "bb_archive.h"
|
||||
|
||||
|
@ -41,7 +39,8 @@ typedef struct huft_t {
|
|||
unsigned char e; /* number of extra bits or operation */
|
||||
unsigned char b; /* number of bits in this code or subcode */
|
||||
union {
|
||||
unsigned short n; /* literal, length base, or distance base */
|
||||
unsigned n; /* literal, length base, or distance base */
|
||||
/* ^^^^^ was "unsigned short", but that results in larger code */
|
||||
struct huft_t *t; /* pointer to next level of table */
|
||||
} v;
|
||||
} huft_t;
|
||||
|
@ -128,6 +127,8 @@ typedef struct state_t {
|
|||
#define gunzip_bb (S()gunzip_bb )
|
||||
#define gunzip_bk (S()gunzip_bk )
|
||||
#define to_read (S()to_read )
|
||||
// #define bytebuffer_max (S()bytebuffer_max )
|
||||
// Both gunzip and unzip can use constant buffer size now (16k):
|
||||
#define bytebuffer_max BB_BUFSIZE
|
||||
#define bytebuffer (S()bytebuffer )
|
||||
#define bytebuffer_offset (S()bytebuffer_offset )
|
||||
|
@ -184,29 +185,26 @@ static const uint16_t mask_bits[] ALIGN2 = {
|
|||
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
|
||||
};
|
||||
|
||||
/* Copy lengths for literal codes 257..285 */
|
||||
static const uint16_t cplens[] ALIGN2 = {
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
|
||||
67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
|
||||
/* Put lengths/offsets and extra bits in a struct of arrays
|
||||
* to make calls to huft_build() have one fewer parameter.
|
||||
*/
|
||||
struct cp_ext {
|
||||
uint16_t cp[31];
|
||||
uint8_t ext[31];
|
||||
};
|
||||
|
||||
/* Copy lengths and extra bits for literal codes 257..285 */
|
||||
/* note: see note #13 above about the 258 in this list. */
|
||||
/* Extra bits for literal codes 257..285 */
|
||||
static const uint8_t cplext[] ALIGN1 = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5,
|
||||
5, 5, 5, 0, 99, 99
|
||||
}; /* 99 == invalid */
|
||||
|
||||
/* Copy offsets for distance codes 0..29 */
|
||||
static const uint16_t cpdist[] ALIGN2 = {
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
|
||||
769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
|
||||
static const struct cp_ext lit ALIGN2 = {
|
||||
/*257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 */
|
||||
/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 */
|
||||
{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 } /* 99 == invalid */
|
||||
};
|
||||
|
||||
/* Extra bits for distance codes */
|
||||
static const uint8_t cpdext[] ALIGN1 = {
|
||||
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
|
||||
11, 11, 12, 12, 13, 13
|
||||
/* Copy offsets and extra bits for distance codes 0..29 */
|
||||
static const struct cp_ext dist ALIGN2 = {
|
||||
/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 */
|
||||
{ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 },
|
||||
{ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 }
|
||||
};
|
||||
|
||||
/* Tables for deflate from PKZIP's appnote.txt. */
|
||||
|
@ -222,10 +220,19 @@ static const uint8_t border[] ALIGN1 = {
|
|||
* each table.
|
||||
* t: table to free
|
||||
*/
|
||||
#define BAD_HUFT(p) ((uintptr_t)(p) & 1)
|
||||
#define ERR_RET ((huft_t*)(uintptr_t)1)
|
||||
static void huft_free(huft_t *p)
|
||||
{
|
||||
huft_t *q;
|
||||
|
||||
/*
|
||||
* If 'p' has the error bit set we have to clear it, otherwise we might run
|
||||
* into a segmentation fault or an invalid pointer to free(p)
|
||||
*/
|
||||
//if (BAD_HUFT(p)) // commented out, since bit clearing has effect only if condition is true
|
||||
p = (huft_t*)((uintptr_t)p & ~(uintptr_t)ERR_RET);
|
||||
|
||||
/* Go through linked list, freeing from the malloced (t[-1]) address. */
|
||||
while (p) {
|
||||
q = (--p)->v.t;
|
||||
|
@ -277,22 +284,23 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current
|
|||
|
||||
|
||||
/* Given a list of code lengths and a maximum table size, make a set of
|
||||
* tables to decode that set of codes. Return zero on success, one if
|
||||
* the given code set is incomplete (the tables are still built in this
|
||||
* case), two if the input is invalid (all zero length codes or an
|
||||
* oversubscribed set of lengths) - in this case stores NULL in *t.
|
||||
* tables to decode that set of codes.
|
||||
*
|
||||
* b: code lengths in bits (all assumed <= BMAX)
|
||||
* n: number of codes (assumed <= N_MAX)
|
||||
* s: number of simple-valued codes (0..s-1)
|
||||
* d: list of base values for non-simple codes
|
||||
* e: list of extra bits for non-simple codes
|
||||
* t: result: starting table
|
||||
* cp_ext->cp,ext: list of base values/extra bits for non-simple codes
|
||||
* m: maximum lookup bits, returns actual
|
||||
* result: starting table
|
||||
*
|
||||
* On error, returns a value with lowest-bit set on error.
|
||||
* It can be just the value of 0x1,
|
||||
* or a valid pointer to a Huffman table, ORed with 0x1 if incompete table
|
||||
* is given: "fixed inflate" decoder feeds us such data.
|
||||
*/
|
||||
static int huft_build(const unsigned *b, const unsigned n,
|
||||
const unsigned s, const unsigned short *d,
|
||||
const unsigned char *e, huft_t **t, unsigned *m)
|
||||
static huft_t* huft_build(const unsigned *b, const unsigned n,
|
||||
const unsigned s, const struct cp_ext *cp_ext,
|
||||
unsigned *m)
|
||||
{
|
||||
unsigned a; /* counter for codes of length k */
|
||||
unsigned c[BMAX + 1]; /* bit length count table */
|
||||
|
@ -303,34 +311,42 @@ static int huft_build(const unsigned *b, const unsigned n,
|
|||
unsigned i; /* counter, current code */
|
||||
unsigned j; /* counter */
|
||||
int k; /* number of bits in current code */
|
||||
unsigned *p; /* pointer into c[], b[], or v[] */
|
||||
const unsigned *p; /* pointer into c[], b[], or v[] */
|
||||
huft_t *q; /* points to current table */
|
||||
huft_t r; /* table entry for structure assignment */
|
||||
huft_t *u[BMAX]; /* table stack */
|
||||
unsigned v[N_MAX]; /* values in order of bit length */
|
||||
unsigned v[N_MAX + 1]; /* values in order of bit length. last v[] is never used */
|
||||
int ws[BMAX + 1]; /* bits decoded stack */
|
||||
int w; /* bits decoded */
|
||||
unsigned x[BMAX + 1]; /* bit offsets, then code stack */
|
||||
unsigned *xp; /* pointer into x */
|
||||
int y; /* number of dummy codes added */
|
||||
unsigned z; /* number of entries in current table */
|
||||
huft_t *result;
|
||||
huft_t **t;
|
||||
|
||||
/* Length of EOB code, if any */
|
||||
eob_len = n > 256 ? b[256] : BMAX;
|
||||
|
||||
*t = NULL;
|
||||
memset(&r, 0, sizeof(r));
|
||||
|
||||
/* Generate counts for each bit length */
|
||||
memset(c, 0, sizeof(c));
|
||||
p = (unsigned *) b; /* cast allows us to reuse p for pointing to b */
|
||||
p = b;
|
||||
i = n;
|
||||
do {
|
||||
c[*p]++; /* assume all entries <= BMAX */
|
||||
p++; /* can't combine with above line (Solaris bug) */
|
||||
} while (--i);
|
||||
if (c[0] == n) { /* null input - all zero length codes */
|
||||
*m = 0;
|
||||
return 2;
|
||||
q = xzalloc(3 * sizeof(*q));
|
||||
//q[0].v.t = NULL;
|
||||
q[1].e = 99; /* invalid code marker */
|
||||
q[1].b = 1;
|
||||
q[2].e = 99; /* invalid code marker */
|
||||
q[2].b = 1;
|
||||
*m = 1;
|
||||
return q + 1;
|
||||
}
|
||||
|
||||
/* Find minimum and maximum length, bound *m by those */
|
||||
|
@ -346,11 +362,11 @@ static int huft_build(const unsigned *b, const unsigned n,
|
|||
for (y = 1 << j; j < i; j++, y <<= 1) {
|
||||
y -= c[j];
|
||||
if (y < 0)
|
||||
return 2; /* bad input: more codes than bits */
|
||||
return ERR_RET; /* bad input: more codes than bits */
|
||||
}
|
||||
y -= c[i];
|
||||
if (y < 0)
|
||||
return 2;
|
||||
return ERR_RET;
|
||||
c[i] += y;
|
||||
|
||||
/* Generate starting offsets into the value table for each length */
|
||||
|
@ -362,8 +378,12 @@ static int huft_build(const unsigned *b, const unsigned n,
|
|||
*xp++ = j;
|
||||
}
|
||||
|
||||
/* Make a table of values in order of bit lengths */
|
||||
p = (unsigned *) b;
|
||||
/* Make a table of values in order of bit lengths.
|
||||
* To detect bad input, unused v[i]'s are set to invalid value UINT_MAX.
|
||||
* In particular, last v[i] is never filled and must not be accessed.
|
||||
*/
|
||||
memset(v, 0xff, sizeof(v));
|
||||
p = b;
|
||||
i = 0;
|
||||
do {
|
||||
j = *p++;
|
||||
|
@ -373,6 +393,8 @@ static int huft_build(const unsigned *b, const unsigned n,
|
|||
} while (++i < n);
|
||||
|
||||
/* Generate the Huffman codes and for each, make the table entries */
|
||||
result = ERR_RET;
|
||||
t = &result;
|
||||
x[0] = i = 0; /* first Huffman code is zero */
|
||||
p = v; /* grab values in bit order */
|
||||
htl = -1; /* no tables yet--level -1 */
|
||||
|
@ -430,14 +452,16 @@ static int huft_build(const unsigned *b, const unsigned n,
|
|||
|
||||
/* set up table entry in r */
|
||||
r.b = (unsigned char) (k - w);
|
||||
if (p >= v + n) {
|
||||
if (/*p >= v + n || -- redundant, caught by the second check: */
|
||||
*p == UINT_MAX /* do we access uninited v[i]? (see memset(v))*/
|
||||
) {
|
||||
r.e = 99; /* out of values--invalid code */
|
||||
} else if (*p < s) {
|
||||
r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is EOB code */
|
||||
r.v.n = (unsigned short) (*p++); /* simple code is just the value */
|
||||
} else {
|
||||
r.e = (unsigned char) e[*p - s]; /* non-simple--look up in lists */
|
||||
r.v.n = d[*p++ - s];
|
||||
r.e = (unsigned char) cp_ext->ext[*p - s]; /* non-simple--look up in lists */
|
||||
r.v.n = cp_ext->cp[*p++ - s];
|
||||
}
|
||||
|
||||
/* fill code-like entries with r */
|
||||
|
@ -462,8 +486,11 @@ static int huft_build(const unsigned *b, const unsigned n,
|
|||
/* return actual size of base table */
|
||||
*m = ws[1];
|
||||
|
||||
/* Return 1 if we were given an incomplete table */
|
||||
return y != 0 && g != 1;
|
||||
if (y != 0 && g != 1) /* we were given an incomplete table */
|
||||
/* return "result" ORed with 1 */
|
||||
return (void*)((uintptr_t)result | 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -515,8 +542,9 @@ static NOINLINE int inflate_codes(STATE_PARAM_ONLY)
|
|||
e = t->e;
|
||||
if (e > 16)
|
||||
do {
|
||||
if (e == 99)
|
||||
abort_unzip(PASS_STATE_ONLY);;
|
||||
if (e == 99) {
|
||||
abort_unzip(PASS_STATE_ONLY);
|
||||
}
|
||||
bb >>= t->b;
|
||||
k -= t->b;
|
||||
e -= 16;
|
||||
|
@ -552,8 +580,9 @@ static NOINLINE int inflate_codes(STATE_PARAM_ONLY)
|
|||
e = t->e;
|
||||
if (e > 16)
|
||||
do {
|
||||
if (e == 99)
|
||||
if (e == 99) {
|
||||
abort_unzip(PASS_STATE_ONLY);
|
||||
}
|
||||
bb >>= t->b;
|
||||
k -= t->b;
|
||||
e -= 16;
|
||||
|
@ -762,14 +791,17 @@ static int inflate_block(STATE_PARAM smallint *e)
|
|||
for (; i < 288; i++) /* make a complete, but wrong code set */
|
||||
ll[i] = 8;
|
||||
bl = 7;
|
||||
huft_build(ll, 288, 257, cplens, cplext, &inflate_codes_tl, &bl);
|
||||
/* huft_build() never return nonzero - we use known data */
|
||||
inflate_codes_tl = huft_build(ll, 288, 257, &lit, &bl);
|
||||
/* ^^^ never returns error here - we use known data */
|
||||
|
||||
/* set up distance table */
|
||||
for (i = 0; i < 30; i++) /* make an incomplete code set */
|
||||
ll[i] = 5;
|
||||
bd = 5;
|
||||
huft_build(ll, 30, 0, cpdist, cpdext, &inflate_codes_td, &bd);
|
||||
inflate_codes_td = huft_build(ll, 30, 0, &dist, &bd);
|
||||
/* ^^^ does return error here! (lsb bit is set) - we gave it incomplete code set */
|
||||
/* clearing error bit: */
|
||||
inflate_codes_td = (void*)((uintptr_t)inflate_codes_td & ~(uintptr_t)1);
|
||||
|
||||
/* set up data for inflate_codes() */
|
||||
inflate_codes_setup(PASS_STATE bl, bd);
|
||||
|
@ -819,8 +851,9 @@ static int inflate_block(STATE_PARAM smallint *e)
|
|||
|
||||
b_dynamic >>= 4;
|
||||
k_dynamic -= 4;
|
||||
if (nl > 286 || nd > 30)
|
||||
if (nl > 286 || nd > 30) {
|
||||
abort_unzip(PASS_STATE_ONLY); /* bad lengths */
|
||||
}
|
||||
|
||||
/* read in bit-length-code lengths */
|
||||
for (j = 0; j < nb; j++) {
|
||||
|
@ -834,9 +867,9 @@ static int inflate_block(STATE_PARAM smallint *e)
|
|||
|
||||
/* build decoding table for trees - single level, 7 bit lookup */
|
||||
bl = 7;
|
||||
i = huft_build(ll, 19, 19, NULL, NULL, &inflate_codes_tl, &bl);
|
||||
if (i != 0) {
|
||||
abort_unzip(PASS_STATE_ONLY); //return i; /* incomplete code set */
|
||||
inflate_codes_tl = huft_build(ll, 19, 19, NULL, &bl);
|
||||
if (BAD_HUFT(inflate_codes_tl)) {
|
||||
abort_unzip(PASS_STATE_ONLY); /* incomplete code set */
|
||||
}
|
||||
|
||||
/* read in literal and distance code lengths */
|
||||
|
@ -899,14 +932,15 @@ static int inflate_block(STATE_PARAM smallint *e)
|
|||
|
||||
/* build the decoding tables for literal/length and distance codes */
|
||||
bl = lbits;
|
||||
|
||||
i = huft_build(ll, nl, 257, cplens, cplext, &inflate_codes_tl, &bl);
|
||||
if (i != 0)
|
||||
inflate_codes_tl = huft_build(ll, nl, 257, &lit, &bl);
|
||||
if (BAD_HUFT(inflate_codes_tl)) {
|
||||
abort_unzip(PASS_STATE_ONLY);
|
||||
}
|
||||
bd = dbits;
|
||||
i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &inflate_codes_td, &bd);
|
||||
if (i != 0)
|
||||
inflate_codes_td = huft_build(ll + nl, nd, 0, &dist, &bd);
|
||||
if (BAD_HUFT(inflate_codes_td)) {
|
||||
abort_unzip(PASS_STATE_ONLY);
|
||||
}
|
||||
|
||||
/* set up data for inflate_codes() */
|
||||
inflate_codes_setup(PASS_STATE bl, bd);
|
||||
|
@ -976,7 +1010,7 @@ inflate_unzip_internal(STATE_PARAM transformer_state_t *xstate)
|
|||
ssize_t nwrote;
|
||||
|
||||
/* Allocate all global buffers (for DYN_ALLOC option) */
|
||||
gunzip_window = xmalloc(GUNZIP_WSIZE);
|
||||
gunzip_window = xzalloc(GUNZIP_WSIZE);
|
||||
gunzip_outbuf_count = 0;
|
||||
gunzip_bytes_out = 0;
|
||||
gunzip_src_fd = xstate->src_fd;
|
||||
|
@ -995,6 +1029,7 @@ inflate_unzip_internal(STATE_PARAM transformer_state_t *xstate)
|
|||
error_msg = "corrupted data";
|
||||
if (setjmp(error_jmp)) {
|
||||
/* Error from deep inside zip machinery */
|
||||
bb_simple_error_msg("corrupted data");
|
||||
n = -1;
|
||||
goto ret;
|
||||
}
|
||||
|
@ -1070,7 +1105,7 @@ static int top_up(STATE_PARAM unsigned n)
|
|||
bytebuffer_offset = 0;
|
||||
bytebuffer_size = full_read(gunzip_src_fd, &bytebuffer[count], bytebuffer_max - count);
|
||||
if ((int)bytebuffer_size < 0) {
|
||||
bb_error_msg(bb_msg_read_error);
|
||||
bb_simple_error_msg(bb_msg_read_error);
|
||||
return 0;
|
||||
}
|
||||
bytebuffer_size += count;
|
||||
|
@ -1122,9 +1157,8 @@ static int check_header_gzip(STATE_PARAM transformer_state_t *xstate)
|
|||
} PACKED formatted;
|
||||
} header;
|
||||
PRAGMA_END_PACKED
|
||||
struct BUG_header {
|
||||
char BUG_header[sizeof(header) == 8 ? 1 : -1];
|
||||
};
|
||||
|
||||
BUILD_BUG_ON(sizeof(header) != 8);
|
||||
|
||||
/*
|
||||
* Rewind bytebuffer. We use the beginning because the header has 8
|
||||
|
@ -1165,6 +1199,7 @@ static int check_header_gzip(STATE_PARAM transformer_state_t *xstate)
|
|||
do {
|
||||
if (!top_up(PASS_STATE 1))
|
||||
return 0;
|
||||
// coverity[tainted_data]
|
||||
} while (bytebuffer[bytebuffer_offset++] != 0);
|
||||
if ((header.formatted.flags & 0x18) != 0x18)
|
||||
break;
|
||||
|
@ -1194,16 +1229,16 @@ unpack_gz_stream(transformer_state_t *xstate)
|
|||
if (check_signature16(xstate, GZIP_MAGIC))
|
||||
return -1;
|
||||
#else
|
||||
if (xstate->check_signature) {
|
||||
if (!xstate->signature_skipped) {
|
||||
uint16_t magic2;
|
||||
|
||||
if (full_read(xstate->src_fd, &magic2, 2) != 2) {
|
||||
bad_magic:
|
||||
bb_error_msg("invalid magic");
|
||||
bb_simple_error_msg("invalid magic");
|
||||
return -1;
|
||||
}
|
||||
if (magic2 == COMPRESS_MAGIC) {
|
||||
xstate->check_signature = 0;
|
||||
xstate->signature_skipped = 2;
|
||||
return unpack_Z_stream(xstate);
|
||||
}
|
||||
if (magic2 != GZIP_MAGIC)
|
||||
|
@ -1230,7 +1265,7 @@ unpack_gz_stream(transformer_state_t *xstate)
|
|||
|
||||
again:
|
||||
if (!check_header_gzip(PASS_STATE xstate)) {
|
||||
bb_error_msg("corrupted data");
|
||||
bb_simple_error_msg("corrupted data");
|
||||
total = -1;
|
||||
goto ret;
|
||||
}
|
||||
|
@ -1243,7 +1278,7 @@ unpack_gz_stream(transformer_state_t *xstate)
|
|||
total += n;
|
||||
|
||||
if (!top_up(PASS_STATE 8)) {
|
||||
bb_error_msg("corrupted data");
|
||||
bb_simple_error_msg("corrupted data");
|
||||
total = -1;
|
||||
goto ret;
|
||||
}
|
||||
|
@ -1251,7 +1286,7 @@ unpack_gz_stream(transformer_state_t *xstate)
|
|||
/* Validate decompression - crc */
|
||||
v32 = buffer_read_le_u32(PASS_STATE_ONLY);
|
||||
if ((~gunzip_crc) != v32) {
|
||||
bb_error_msg("crc error");
|
||||
bb_simple_error_msg("crc error");
|
||||
total = -1;
|
||||
goto ret;
|
||||
}
|
||||
|
@ -1259,7 +1294,7 @@ unpack_gz_stream(transformer_state_t *xstate)
|
|||
/* Validate decompression - size */
|
||||
v32 = buffer_read_le_u32(PASS_STATE_ONLY);
|
||||
if ((uint32_t)gunzip_bytes_out != v32) {
|
||||
bb_error_msg("incorrect length");
|
||||
bb_simple_error_msg("incorrect length");
|
||||
total = -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/* vi: set sw=4 ts=4: */
|
||||
/* uncompress for busybox -- (c) 2002 Robert Griebl
|
||||
/*
|
||||
* uncompress for busybox -- (c) 2002 Robert Griebl
|
||||
*
|
||||
* based on the original compress42.c source
|
||||
* (see disclaimer below)
|
||||
*/
|
||||
|
||||
/* (N)compress42.c - File compression ala IEEE Computer, Mar 1992.
|
||||
*
|
||||
* Authors:
|
||||
|
@ -21,9 +21,7 @@
|
|||
* marc@suse.de : a small security fix for a buffer overflow
|
||||
*
|
||||
* [... History snipped ...]
|
||||
*
|
||||
*/
|
||||
|
||||
#include "libbb.h"
|
||||
#include "bb_archive.h"
|
||||
|
||||
|
@ -115,7 +113,7 @@ unpack_Z_stream(transformer_state_t *xstate)
|
|||
/* xread isn't good here, we have to return - caller may want
|
||||
* to do some cleanup (e.g. delete incomplete unpacked file etc) */
|
||||
if (full_read(xstate->src_fd, inbuf, 1) != 1) {
|
||||
bb_error_msg("short read");
|
||||
bb_simple_error_msg("short read");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -168,7 +166,7 @@ unpack_Z_stream(transformer_state_t *xstate)
|
|||
if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) {
|
||||
rsize = safe_read(xstate->src_fd, inbuf + insize, IBUFSIZ);
|
||||
if (rsize < 0)
|
||||
bb_error_msg_and_err(bb_msg_read_error);
|
||||
bb_simple_error_msg_and_die(bb_msg_read_error);
|
||||
insize += rsize;
|
||||
}
|
||||
|
||||
|
@ -202,7 +200,7 @@ unpack_Z_stream(transformer_state_t *xstate)
|
|||
|
||||
if (oldcode == -1) {
|
||||
if (code >= 256)
|
||||
bb_error_msg_and_err("corrupted data"); /* %ld", code); */
|
||||
bb_simple_error_msg_and_die("corrupted data"); /* %ld", code); */
|
||||
oldcode = code;
|
||||
finchar = (int) oldcode;
|
||||
outbuf[outpos++] = (unsigned char) finchar;
|
||||
|
@ -238,7 +236,7 @@ unpack_Z_stream(transformer_state_t *xstate)
|
|||
insize, posbits, p[-1], p[0], p[1], p[2], p[3],
|
||||
(posbits & 07));
|
||||
*/
|
||||
bb_error_msg("corrupted data");
|
||||
bb_simple_error_msg("corrupted data");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -249,7 +247,7 @@ unpack_Z_stream(transformer_state_t *xstate)
|
|||
/* Generate output characters in reverse order */
|
||||
while (code >= 256) {
|
||||
if (stackp <= &htabof(0))
|
||||
bb_error_msg_and_err("corrupted data");
|
||||
bb_simple_error_msg_and_die("corrupted data");
|
||||
*--stackp = tab_suffixof(code);
|
||||
code = tab_prefixof(code);
|
||||
}
|
||||
|
@ -301,7 +299,6 @@ unpack_Z_stream(transformer_state_t *xstate)
|
|||
/* Remember previous code. */
|
||||
oldcode = incode;
|
||||
}
|
||||
|
||||
} while (rsize > 0);
|
||||
|
||||
if (outpos > 0) {
|
||||
|
|
|
@ -11,6 +11,13 @@
|
|||
#include "libbb.h"
|
||||
#include "bb_archive.h"
|
||||
|
||||
#if 0
|
||||
# define dbg(...) bb_error_msg(__VA_ARGS__)
|
||||
#else
|
||||
# define dbg(...) ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
#if ENABLE_FEATURE_LZMA_FAST
|
||||
# define speed_inline ALWAYS_INLINE
|
||||
# define size_inline
|
||||
|
@ -52,7 +59,7 @@ static void rc_read(rc_t *rc)
|
|||
//TODO: return -1 instead
|
||||
//This will make unlzma delete broken unpacked file on unpack errors
|
||||
if (buffer_size <= 0)
|
||||
bb_error_msg_and_die("unexpected EOF");
|
||||
bb_simple_error_msg_and_die("unexpected EOF");
|
||||
rc->buffer_end = RC_BUFFER + buffer_size;
|
||||
rc->ptr = RC_BUFFER;
|
||||
}
|
||||
|
@ -220,9 +227,10 @@ unpack_lzma_stream(transformer_state_t *xstate)
|
|||
rc_t *rc;
|
||||
int i;
|
||||
uint8_t *buffer;
|
||||
uint32_t buffer_size;
|
||||
uint8_t previous_byte = 0;
|
||||
size_t buffer_pos = 0, global_pos = 0;
|
||||
ssize_t nwrote;
|
||||
ssize_t nwrote = 0;
|
||||
int len = 0;
|
||||
int state = 0;
|
||||
uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
|
||||
|
@ -230,7 +238,7 @@ unpack_lzma_stream(transformer_state_t *xstate)
|
|||
if (full_read(xstate->src_fd, &header, sizeof(header)) != sizeof(header)
|
||||
|| header.pos >= (9 * 5 * 5)
|
||||
) {
|
||||
bb_error_msg("bad lzma header");
|
||||
bb_simple_error_msg("bad lzma header");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -250,7 +258,8 @@ unpack_lzma_stream(transformer_state_t *xstate)
|
|||
if (header.dict_size == 0)
|
||||
header.dict_size++;
|
||||
|
||||
buffer = xmalloc((size_t)MIN(header.dst_size, header.dict_size));
|
||||
buffer_size = (uint32_t)MIN(header.dst_size, header.dict_size);
|
||||
buffer = xmalloc(buffer_size);
|
||||
|
||||
{
|
||||
int num_probs;
|
||||
|
@ -267,14 +276,14 @@ unpack_lzma_stream(transformer_state_t *xstate)
|
|||
while ((uint64_t)global_pos + buffer_pos < header.dst_size) {
|
||||
int pos_state = (buffer_pos + global_pos) & pos_state_mask;
|
||||
uintptr_t off1 = LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state;
|
||||
uint16_t *prob1 = p + off1;
|
||||
uint16_t *prob = p + off1;
|
||||
|
||||
if (!rc_is_bit_1(rc, prob1)) {
|
||||
if (!rc_is_bit_1(rc, prob)) {
|
||||
static const char next_state[LZMA_NUM_STATES] =
|
||||
{ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };
|
||||
int mi = 1;
|
||||
|
||||
prob1 = (p + LZMA_LITERAL
|
||||
prob = (p + LZMA_LITERAL
|
||||
+ (LZMA_LIT_SIZE * ((((buffer_pos + global_pos) & literal_pos_mask) << lc)
|
||||
+ (previous_byte >> (8 - lc))
|
||||
)
|
||||
|
@ -283,23 +292,27 @@ unpack_lzma_stream(transformer_state_t *xstate)
|
|||
|
||||
if (state >= LZMA_NUM_LIT_STATES) {
|
||||
int match_byte;
|
||||
uint32_t pos = (uint32_t)(buffer_pos - rep0);
|
||||
uint32_t pos;
|
||||
|
||||
while (pos >= header.dict_size)
|
||||
pos = (uint32_t)(buffer_pos - rep0);
|
||||
if ((int32_t)pos < 0) {
|
||||
pos += header.dict_size;
|
||||
if ((int32_t)pos < 0)
|
||||
goto bad;
|
||||
}
|
||||
match_byte = buffer[pos];
|
||||
do {
|
||||
int bit;
|
||||
|
||||
match_byte <<= 1;
|
||||
bit = match_byte & 0x100;
|
||||
bit ^= (rc_get_bit(rc, prob1 + 0x100 + bit + mi, &mi) << 8); /* 0x100 or 0 */
|
||||
bit ^= (rc_get_bit(rc, prob + 0x100 + bit + mi, &mi) << 8); /* 0x100 or 0 */
|
||||
if (bit)
|
||||
break;
|
||||
} while (mi < 0x100);
|
||||
}
|
||||
while (mi < 0x100) {
|
||||
rc_get_bit(rc, prob1 + mi, &mi);
|
||||
rc_get_bit(rc, prob + mi, &mi);
|
||||
}
|
||||
|
||||
state = next_state[state];
|
||||
|
@ -336,14 +349,24 @@ unpack_lzma_stream(transformer_state_t *xstate)
|
|||
} else {
|
||||
prob2 += LZMA_IS_REP_G0 - LZMA_IS_REP;
|
||||
if (!rc_is_bit_1(rc, prob2)) {
|
||||
uintptr_t off2 = LZMA_IS_REP_0_LONG + (state << LZMA_NUM_POS_BITS_MAX) + pos_state;
|
||||
prob2 = p + off2;
|
||||
prob2 = (p + LZMA_IS_REP_0_LONG
|
||||
+ (state << LZMA_NUM_POS_BITS_MAX)
|
||||
+ pos_state
|
||||
);
|
||||
if (!rc_is_bit_1(rc, prob2)) {
|
||||
#if ENABLE_FEATURE_LZMA_FAST
|
||||
uint32_t pos = buffer_pos - rep0;
|
||||
uint32_t pos;
|
||||
state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
|
||||
while (pos >= header.dict_size)
|
||||
|
||||
pos = buffer_pos - rep0;
|
||||
if ((int32_t)pos < 0) {
|
||||
pos += header.dict_size;
|
||||
/* see unzip_bad_lzma_2.zip: */
|
||||
if (pos >= buffer_size) {
|
||||
dbg("%d pos:%d buffer_size:%d", __LINE__, pos, buffer_size);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
previous_byte = buffer[pos];
|
||||
goto one_byte1;
|
||||
#else
|
||||
|
@ -418,6 +441,9 @@ unpack_lzma_stream(transformer_state_t *xstate)
|
|||
for (; num_bits2 != LZMA_NUM_ALIGN_BITS; num_bits2--)
|
||||
rep0 = (rep0 << 1) | rc_direct_bit(rc);
|
||||
rep0 <<= LZMA_NUM_ALIGN_BITS;
|
||||
// Note: (int32_t)rep0 may be < 0 here
|
||||
// (I have linux-3.3.4.tar.lzma which has it).
|
||||
// I moved the check after "++rep0 == 0" check below.
|
||||
prob3 = p + LZMA_ALIGN;
|
||||
}
|
||||
i2 = 1;
|
||||
|
@ -428,16 +454,43 @@ unpack_lzma_stream(transformer_state_t *xstate)
|
|||
i2 <<= 1;
|
||||
}
|
||||
}
|
||||
if (++rep0 == 0)
|
||||
rep0++;
|
||||
if ((int32_t)rep0 <= 0) {
|
||||
if (rep0 == 0)
|
||||
break;
|
||||
dbg("%d rep0:%d", __LINE__, rep0);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
len += LZMA_MATCH_MIN_LEN;
|
||||
/*
|
||||
* LZMA SDK has this optimized:
|
||||
* it precalculates size and copies many bytes
|
||||
* in a loop with simpler checks, a-la:
|
||||
* do
|
||||
* *(dest) = *(dest + ofs);
|
||||
* while (++dest != lim);
|
||||
* and
|
||||
* do {
|
||||
* buffer[buffer_pos++] = buffer[pos];
|
||||
* if (++pos == header.dict_size)
|
||||
* pos = 0;
|
||||
* } while (--cur_len != 0);
|
||||
* Our code is slower (more checks per byte copy):
|
||||
*/
|
||||
IF_NOT_FEATURE_LZMA_FAST(string:)
|
||||
do {
|
||||
uint32_t pos = (uint32_t)(buffer_pos - rep0);
|
||||
while (pos >= header.dict_size)
|
||||
if ((int32_t)pos < 0) {
|
||||
pos += header.dict_size;
|
||||
/* bug 10436 has an example file where this triggers: */
|
||||
//if ((int32_t)pos < 0)
|
||||
// goto bad;
|
||||
/* more stringent test (see unzip_bad_lzma_1.zip): */
|
||||
if (pos >= buffer_size)
|
||||
goto bad;
|
||||
}
|
||||
previous_byte = buffer[pos];
|
||||
IF_NOT_FEATURE_LZMA_FAST(one_byte2:)
|
||||
buffer[buffer_pos++] = previous_byte;
|
||||
|
@ -453,6 +506,9 @@ unpack_lzma_stream(transformer_state_t *xstate)
|
|||
} while (len != 0 && buffer_pos < header.dst_size);
|
||||
/* FIXME: ...........^^^^^
|
||||
* shouldn't it be "global_pos + buffer_pos < header.dst_size"?
|
||||
* It probably should, but it is a "do we accidentally
|
||||
* unpack more bytes than expected?" check - which
|
||||
* never happens for well-formed compression data...
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -312,6 +312,7 @@ IF_DESKTOP(long long) int FAST_FUNC unpack_zip_stream(transformer_state_t *xstat
|
|||
xstate->dst_size = zip_header.formatted.ucmpsize;
|
||||
xstate->dst_name = xzalloc(zip_header.formatted.filename_len + 1);
|
||||
safe_read(xstate->src_fd, xstate->dst_name, zip_header.formatted.filename_len);
|
||||
xstate->dst_name[zip_header.formatted.filename_len] = 0;
|
||||
n = transformer_switch_file(xstate);
|
||||
free(xstate->dst_name);
|
||||
if (n < 0)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
/*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||
*/
|
||||
|
||||
#include "libbb.h"
|
||||
#include "bb_archive.h"
|
||||
|
||||
|
@ -12,6 +11,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
|
|||
struct tm *ptm = &tm_time; //localtime(&file_header->mtime);
|
||||
|
||||
#if ENABLE_FEATURE_TAR_UNAME_GNAME
|
||||
char modestr[12];
|
||||
char uid[sizeof(int)*3 + 2];
|
||||
/*char gid[sizeof(int)*3 + 2];*/
|
||||
char *user;
|
||||
|
@ -30,7 +30,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
|
|||
group = utoa(file_header->gid);
|
||||
}
|
||||
printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s",
|
||||
bb_mode_string(file_header->mode),
|
||||
bb_mode_string(modestr, file_header->mode),
|
||||
user,
|
||||
group,
|
||||
file_header->size,
|
||||
|
@ -47,7 +47,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
|
|||
localtime_r(&file_header->mtime, ptm);
|
||||
|
||||
printf("%s %u/%u %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s",
|
||||
bb_mode_string(file_header->mode),
|
||||
bb_mode_string(modestr, file_header->mode),
|
||||
(unsigned)file_header->uid,
|
||||
(unsigned)file_header->gid,
|
||||
file_header->size,
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
#define IF_NOT_FEATURE_LZMA_FAST(x) x
|
||||
|
||||
#define uoff_t unsigned off_t
|
||||
#define OFF_FMT "I64"
|
||||
#define OFF_FMT PRIi64
|
||||
|
||||
#ifndef _MODE_T_
|
||||
#define _MODE_T_
|
||||
|
@ -86,6 +86,8 @@ typedef unsigned int uid_t;
|
|||
#define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
|
||||
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
|
||||
|
||||
#ifndef get_le64
|
||||
#define get_le64(ptr) (*(const uint64_t *)(ptr))
|
||||
#endif
|
||||
|
@ -146,6 +148,9 @@ extern unsigned long* bled_cancel_request;
|
|||
#define bb_error_msg_and_err(...) do {bb_error_msg(__VA_ARGS__); goto err;} while(0)
|
||||
#define bb_perror_msg bb_error_msg
|
||||
#define bb_perror_msg_and_die bb_error_msg_and_die
|
||||
#define bb_simple_error_msg bb_error_msg
|
||||
#define bb_simple_perror_msg_and_die bb_error_msg_and_die
|
||||
#define bb_simple_error_msg_and_die bb_error_msg_and_die
|
||||
#define bb_putchar putchar
|
||||
|
||||
static inline void *xrealloc(void *ptr, size_t size) {
|
||||
|
@ -157,7 +162,7 @@ static inline void *xrealloc(void *ptr, size_t size) {
|
|||
|
||||
#define bb_msg_read_error "read error"
|
||||
#define bb_msg_write_error "write error"
|
||||
#define bb_mode_string(mode) "[not implemented]"
|
||||
#define bb_mode_string(str, mode) "[not implemented]"
|
||||
#define bb_copyfd_exact_size(fd1, fd2, size) bb_error_msg("Not implemented")
|
||||
#define bb_make_directory(path, mode, flags) SHCreateDirectoryExU(NULL, path, NULL)
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ void FAST_FUNC init_transformer_state(transformer_state_t *xstate)
|
|||
|
||||
int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16)
|
||||
{
|
||||
if (xstate->check_signature) {
|
||||
if (!xstate->signature_skipped) {
|
||||
uint16_t magic2;
|
||||
if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) {
|
||||
bb_error_msg("invalid magic");
|
||||
|
|
|
@ -486,11 +486,11 @@ static __always_inline void XZ_FUNC rc_normalize(struct rc_dec *rc)
|
|||
}
|
||||
|
||||
/*
|
||||
* Decode one bit. In some versions, this function has been splitted in three
|
||||
* Decode one bit. In some versions, this function has been split in three
|
||||
* functions so that the compiler is supposed to be able to more easily avoid
|
||||
* an extra branch. In this particular version of the LZMA decoder, this
|
||||
* doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3
|
||||
* on x86). Using a non-splitted version results in nicer looking code too.
|
||||
* on x86). Using a non-split version results in nicer looking code too.
|
||||
*
|
||||
* NOTE: This must return an int. Do not make it return a bool or the speed
|
||||
* of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care,
|
||||
|
@ -788,6 +788,7 @@ static void XZ_FUNC lzma_reset(struct xz_dec_lzma2 *s)
|
|||
*/
|
||||
probs = s->lzma.is_match[0];
|
||||
for (i = 0; i < PROBS_TOTAL; ++i)
|
||||
// coverity[overrun-local]
|
||||
probs[i] = RC_BIT_MODEL_TOTAL / 2;
|
||||
|
||||
rc_reset(&s->rc);
|
||||
|
@ -995,10 +996,8 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run(
|
|||
s->lzma2.need_props = false;
|
||||
s->lzma2.next_sequence
|
||||
= SEQ_PROPERTIES;
|
||||
|
||||
} else if (s->lzma2.need_props) {
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
} else {
|
||||
s->lzma2.next_sequence
|
||||
= SEQ_LZMA_PREPARE;
|
||||
|
@ -1044,6 +1043,7 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run(
|
|||
return XZ_DATA_ERROR;
|
||||
|
||||
s->lzma2.sequence = SEQ_LZMA_PREPARE;
|
||||
// Fall through
|
||||
|
||||
case SEQ_LZMA_PREPARE:
|
||||
if (s->lzma2.compressed < RC_INIT_BYTES)
|
||||
|
@ -1054,6 +1054,7 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run(
|
|||
|
||||
s->lzma2.compressed -= RC_INIT_BYTES;
|
||||
s->lzma2.sequence = SEQ_LZMA_RUN;
|
||||
// Fall through
|
||||
|
||||
case SEQ_LZMA_RUN:
|
||||
/*
|
||||
|
@ -1080,7 +1081,6 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run(
|
|||
|
||||
rc_reset(&s->rc);
|
||||
s->lzma2.sequence = SEQ_CONTROL;
|
||||
|
||||
} else if (b->out_pos == b->out_size
|
||||
|| (b->in_pos == b->in_size
|
||||
&& s->temp.size
|
||||
|
|
|
@ -353,7 +353,6 @@ static enum xz_ret XZ_FUNC crc32_validate(struct xz_dec *s, struct xz_buf *b)
|
|||
return XZ_DATA_ERROR;
|
||||
|
||||
s->pos += 8;
|
||||
|
||||
} while (s->pos < 32);
|
||||
|
||||
s->crc32 = 0;
|
||||
|
@ -546,7 +545,7 @@ static enum xz_ret XZ_FUNC dec_block_header(struct xz_dec *s)
|
|||
return XZ_OK;
|
||||
}
|
||||
|
||||
static enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b)
|
||||
static NOINLINE enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
enum xz_ret ret;
|
||||
|
||||
|
@ -753,7 +752,6 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b)
|
|||
b->in_pos = in_start;
|
||||
b->out_pos = out_start;
|
||||
}
|
||||
|
||||
} else if (ret == XZ_OK && in_start == b->in_pos
|
||||
&& out_start == b->out_pos) {
|
||||
if (s->allow_buf_error)
|
||||
|
|
|
@ -468,8 +468,11 @@ BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LP
|
|||
ctime = UINT32_MAX;
|
||||
inode.i_mode = 0100644;
|
||||
inode.i_links_count = 1;
|
||||
// coverity[store_truncates_time_t]
|
||||
inode.i_atime = (uint32_t)ctime;
|
||||
// coverity[store_truncates_time_t]
|
||||
inode.i_ctime = (uint32_t)ctime;
|
||||
// coverity[store_truncates_time_t]
|
||||
inode.i_mtime = (uint32_t)ctime;
|
||||
inode.i_size = fsize;
|
||||
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 3.21.1934"
|
||||
CAPTION "Rufus 3.21.1935"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -395,8 +395,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,21,1934,0
|
||||
PRODUCTVERSION 3,21,1934,0
|
||||
FILEVERSION 3,21,1935,0
|
||||
PRODUCTVERSION 3,21,1935,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -414,13 +414,13 @@ BEGIN
|
|||
VALUE "Comments", "https://rufus.ie"
|
||||
VALUE "CompanyName", "Akeo Consulting"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "3.21.1934"
|
||||
VALUE "FileVersion", "3.21.1935"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "© 2011-2022 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
VALUE "OriginalFilename", "rufus-3.21.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "3.21.1934"
|
||||
VALUE "ProductVersion", "3.21.1935"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
Loading…
Reference in a new issue