[cmp] update Bled to latest

* Also try to fix the fallthrough Coverity warning in format_ext.c
This commit is contained in:
Pete Batard 2022-09-14 19:29:11 +02:00
parent 2cf183e9f1
commit 07d1fdcc2f
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
15 changed files with 485 additions and 267 deletions

View File

@ -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,41 +203,47 @@ 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;)
/* Source */
int src_fd;
int src_fd;
/* Output */
int dst_fd;
const char *dst_dir; /* if non-NULL, extract to dir */
char *dst_name;
uint64_t dst_size;
size_t mem_output_size_max; /* if non-zero, decompress to RAM instead of fd */
size_t mem_output_size;
char *mem_output_buf;
int dst_fd;
const char *dst_dir; /* if non-NULL, extract to dir */
char *dst_name;
uint64_t dst_size;
size_t mem_output_size_max; /* if non-zero, decompress to RAM instead of fd */
size_t mem_output_size;
char *mem_output_buf;
uint64_t bytes_out;
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 */
uint64_t bytes_out;
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))

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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;
@ -619,7 +641,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
/* Subtract the 1 copy we'd output anyway to get extras */
--bd->writeCopies;
}
} /* for(;;) */
} /* for (;;) */
/* Decompression of this input block completed successfully */
bd->writeCRC = CRC = ~CRC;
@ -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 */
@ -773,7 +801,7 @@ unpack_bz2_stream(transformer_state_t *xstate)
/* Observed case when i == RETVAL_OK:
* "bzcat z.bz2", where "z.bz2" is a bzipped zero-length file
* (to be exact, z.bz2 is exactly these 14 bytes:
* 42 5a 68 39 17 72 45 38 50 90 00 00 00 00).
* 42 5a 68 39 17 72 45 38 50 90 00 00 00 00).
*/
&& i != RETVAL_OK
) {
@ -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[] = {

View File

@ -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;
}

View File

@ -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) {

View File

@ -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)
break;
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...
*/
}
}

View File

@ -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)

View File

@ -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,

View File

@ -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)

View File

@ -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");

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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"