mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
Vendor import of xz 5.8.4 (trimmed)
This commit is contained in:
1 parent
788f701923
commit
9b26803758
29 files changed
+2013
-284
No files matched your search
@@ -65,6 +65,7 @@ has been important. :-)
|
||||
- Daniel Mealha Cabrita
|
||||
- Daniel Packard
|
||||
- Daniel Richard G.
|
||||
- Darren Carreras
|
||||
- David Burklund
|
||||
- Denis Excoffier
|
||||
- Derwin McGeary
|
||||
@@ -96,6 +97,7 @@ has been important. :-)
|
||||
- Gabriela Gutierrez
|
||||
- Gilles Espinasse
|
||||
- Gregory Margo
|
||||
- Guanni Qu
|
||||
- Guillaume Outters
|
||||
- Guiorgy Potskhishvili
|
||||
- H. Peter Anvin
|
||||
@@ -178,8 +180,10 @@ has been important. :-)
|
||||
- Nicholas Jackson
|
||||
- Nobuhiro Iwamatsu
|
||||
- Ole André Vadla Ravnås
|
||||
- Omkhar Arasaratnam
|
||||
- Orange Tsai
|
||||
- Orgad Shaneh
|
||||
- Otto Kekäläinen
|
||||
- Patrick J. Volkerding
|
||||
- Paul Eggert
|
||||
- Paul Townsend
|
||||
@@ -190,6 +194,7 @@ has been important. :-)
|
||||
- Peter O'Gorman
|
||||
- Peter Pallinger
|
||||
- Peter Seiderer
|
||||
- Phuc An
|
||||
- Pierre-Yves Martin
|
||||
- Pilorz Wojciech
|
||||
- Pino Toscano
|
||||
@@ -245,6 +250,7 @@ has been important. :-)
|
||||
- Xi Ruoyao
|
||||
- Xin Li
|
||||
- Yifeng Li
|
||||
- Zayed Al-Saidi
|
||||
- 榆柳松 (ZhengSen Wang)
|
||||
|
||||
Companies:
|
||||
|
||||
+29
-12
@@ -24,6 +24,29 @@
|
||||
#include <sys/utsname.h>
|
||||
|
||||
|
||||
// In case we are being compiled against an old <linux/landlock.h>,
|
||||
// provide fallbacks for handled_access_fs flags that were added in
|
||||
// Landlock ABI versions 2, 3, 5, and 9. This way we need fewer #ifdefs
|
||||
// later on and, more importantly, these flags are then supported if
|
||||
// the program is run under a kernel that supports a newer Landlock ABI
|
||||
// than the current <linux/landlock.h>.
|
||||
//
|
||||
// NOTE: There are no fallbacks for ABI 4 and 6 features because they
|
||||
// require an extended struct landlock_ruleset_attr.
|
||||
#ifndef LANDLOCK_ACCESS_FS_REFER
|
||||
# define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
|
||||
#endif
|
||||
#ifndef LANDLOCK_ACCESS_FS_TRUNCATE
|
||||
# define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14)
|
||||
#endif
|
||||
#ifndef LANDLOCK_ACCESS_FS_IOCTL_DEV
|
||||
# define LANDLOCK_ACCESS_FS_IOCTL_DEV (1ULL << 15)
|
||||
#endif
|
||||
#ifndef LANDLOCK_ACCESS_FS_RESOLVE_UNIX
|
||||
# define LANDLOCK_ACCESS_FS_RESOLVE_UNIX (1ULL << 16)
|
||||
#endif
|
||||
|
||||
|
||||
/// \brief Initialize Landlock ruleset attributes to forbid everything
|
||||
///
|
||||
/// The supported Landlock ABI is checked at runtime and only the supported
|
||||
@@ -87,15 +110,10 @@ my_landlock_ruleset_attr_forbid_all(struct landlock_ruleset_attr *attr)
|
||||
| LANDLOCK_ACCESS_FS_MAKE_FIFO
|
||||
| LANDLOCK_ACCESS_FS_MAKE_BLOCK
|
||||
| LANDLOCK_ACCESS_FS_MAKE_SYM
|
||||
#ifdef LANDLOCK_ACCESS_FS_REFER
|
||||
| LANDLOCK_ACCESS_FS_REFER // ABI 2
|
||||
#endif
|
||||
#ifdef LANDLOCK_ACCESS_FS_TRUNCATE
|
||||
| LANDLOCK_ACCESS_FS_TRUNCATE // ABI 3
|
||||
#endif
|
||||
#ifdef LANDLOCK_ACCESS_FS_IOCTL_DEV
|
||||
| LANDLOCK_ACCESS_FS_IOCTL_DEV // ABI 5
|
||||
#endif
|
||||
| LANDLOCK_ACCESS_FS_RESOLVE_UNIX // ABI 9
|
||||
;
|
||||
|
||||
#ifdef LANDLOCK_ACCESS_NET_BIND_TCP
|
||||
@@ -115,15 +133,11 @@ my_landlock_ruleset_attr_forbid_all(struct landlock_ruleset_attr *attr)
|
||||
// Disable flags that require a new ABI version.
|
||||
switch (abi_version) {
|
||||
case 1:
|
||||
#ifdef LANDLOCK_ACCESS_FS_REFER
|
||||
attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER;
|
||||
#endif
|
||||
FALLTHROUGH;
|
||||
|
||||
case 2:
|
||||
#ifdef LANDLOCK_ACCESS_FS_TRUNCATE
|
||||
attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_TRUNCATE;
|
||||
#endif
|
||||
FALLTHROUGH;
|
||||
|
||||
case 3:
|
||||
@@ -133,9 +147,7 @@ my_landlock_ruleset_attr_forbid_all(struct landlock_ruleset_attr *attr)
|
||||
FALLTHROUGH;
|
||||
|
||||
case 4:
|
||||
#ifdef LANDLOCK_ACCESS_FS_IOCTL_DEV
|
||||
attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV;
|
||||
#endif
|
||||
FALLTHROUGH;
|
||||
|
||||
case 5:
|
||||
@@ -152,6 +164,11 @@ my_landlock_ruleset_attr_forbid_all(struct landlock_ruleset_attr *attr)
|
||||
|
||||
FALLTHROUGH;
|
||||
|
||||
case 7:
|
||||
case 8:
|
||||
attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_RESOLVE_UNIX;
|
||||
FALLTHROUGH;
|
||||
|
||||
default:
|
||||
// We only know about the features of the ABIs 1-6.
|
||||
break;
|
||||
|
||||
@@ -935,7 +935,10 @@ extern LZMA_API(lzma_ret) lzma_lzip_decoder(
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached.
|
||||
* The minimum required memlimit value was stored to *memlimit.
|
||||
* - LZMA_BUF_ERROR: Output buffer was too small.
|
||||
* - LZMA_BUF_ERROR: Output buffer was too small. (liblzma 5.8.3
|
||||
* and older have a bug: LZMA_BUF_ERROR may be returned when
|
||||
* the input seems to be truncated. The correct error code
|
||||
* would be LZMA_DATA_ERROR.)
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_buffer_decode(
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
* ways to limit the resource usage. Applications linking against liblzma
|
||||
* need to do the actual decisions how much resources to let liblzma to use.
|
||||
* To ease making these decisions, liblzma provides functions to find out
|
||||
* the relevant capabilities of the underlying hardware. Currently there
|
||||
* is only a function to find out the amount of RAM, but in the future there
|
||||
* will be also a function to detect how many concurrent threads the system
|
||||
* can run.
|
||||
* the relevant capabilities of the underlying hardware.
|
||||
*
|
||||
* \note On some operating systems, these function may temporarily
|
||||
* load a shared library or open file descriptor(s) to find out
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define LZMA_VERSION_MINOR 8
|
||||
|
||||
/** \brief Patch version number of the liblzma release. */
|
||||
#define LZMA_VERSION_PATCH 3
|
||||
#define LZMA_VERSION_PATCH 4
|
||||
|
||||
/**
|
||||
* \brief Version stability marker
|
||||
|
||||
@@ -50,9 +50,15 @@ crc32_arch_optimized(const uint8_t *buf, size_t size, uint32_t crc)
|
||||
{
|
||||
crc = ~crc;
|
||||
|
||||
if (size >= 8) {
|
||||
// Align the input buffer because this was shown to be
|
||||
// significantly faster than unaligned accesses.
|
||||
if (size < 8) {
|
||||
while (size > 0) {
|
||||
crc = __crc32b(crc, *buf++);
|
||||
--size;
|
||||
}
|
||||
} else {
|
||||
// We have at least 8 bytes of input. Align the input buffer.
|
||||
// Aligned is faster than unaligned access and works also on
|
||||
// strict-align targets.
|
||||
const size_t align = (0 - (uintptr_t)buf) & 7;
|
||||
|
||||
if (align & 1)
|
||||
@@ -79,23 +85,21 @@ crc32_arch_optimized(const uint8_t *buf, size_t size, uint32_t crc)
|
||||
buf < limit; buf += 8)
|
||||
crc = __crc32d(crc, aligned_read64le(buf));
|
||||
|
||||
size &= 7;
|
||||
}
|
||||
// Process the remaining 0-7 bytes.
|
||||
if (size & 4) {
|
||||
crc = __crc32w(crc, aligned_read32le(buf));
|
||||
buf += 4;
|
||||
}
|
||||
|
||||
// Process the remaining bytes that are not 8 byte aligned.
|
||||
if (size & 4) {
|
||||
crc = __crc32w(crc, aligned_read32le(buf));
|
||||
buf += 4;
|
||||
}
|
||||
if (size & 2) {
|
||||
crc = __crc32h(crc, aligned_read16le(buf));
|
||||
buf += 2;
|
||||
}
|
||||
|
||||
if (size & 2) {
|
||||
crc = __crc32h(crc, aligned_read16le(buf));
|
||||
buf += 2;
|
||||
if (size & 1)
|
||||
crc = __crc32b(crc, *buf);
|
||||
}
|
||||
|
||||
if (size & 1)
|
||||
crc = __crc32b(crc, *buf);
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,13 @@ crc32_arch_optimized(const uint8_t *buf, size_t size, uint32_t crc_unsigned)
|
||||
{
|
||||
int32_t crc = (int32_t)~crc_unsigned;
|
||||
|
||||
if (size >= 8) {
|
||||
if (size < 8) {
|
||||
while (size > 0) {
|
||||
crc = __crc_w_b_w((int8_t)*buf++, crc);
|
||||
--size;
|
||||
}
|
||||
} else {
|
||||
// We have at least 8 bytes of input. Align the input buffer.
|
||||
const size_t align = (0 - (uintptr_t)buf) & 7;
|
||||
|
||||
if (align & 1)
|
||||
@@ -39,26 +45,26 @@ crc32_arch_optimized(const uint8_t *buf, size_t size, uint32_t crc_unsigned)
|
||||
|
||||
size -= align;
|
||||
|
||||
// Process 8 bytes at a time.
|
||||
for (const uint8_t *limit = buf + (size & ~(size_t)7);
|
||||
buf < limit; buf += 8)
|
||||
crc = __crc_w_d_w((int64_t)aligned_read64le(buf), crc);
|
||||
|
||||
size &= 7;
|
||||
}
|
||||
// Process the remaining 0-7 bytes.
|
||||
if (size & 4) {
|
||||
crc = __crc_w_w_w((int32_t)aligned_read32le(buf), crc);
|
||||
buf += 4;
|
||||
}
|
||||
|
||||
if (size & 4) {
|
||||
crc = __crc_w_w_w((int32_t)aligned_read32le(buf), crc);
|
||||
buf += 4;
|
||||
}
|
||||
if (size & 2) {
|
||||
crc = __crc_w_h_w((int16_t)aligned_read16le(buf), crc);
|
||||
buf += 2;
|
||||
}
|
||||
|
||||
if (size & 2) {
|
||||
crc = __crc_w_h_w((int16_t)aligned_read16le(buf), crc);
|
||||
buf += 2;
|
||||
if (size & 1)
|
||||
crc = __crc_w_b_w((int8_t)*buf, crc);
|
||||
}
|
||||
|
||||
if (size & 1)
|
||||
crc = __crc_w_b_w((int8_t)*buf, crc);
|
||||
|
||||
return (uint32_t)~crc;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,8 +152,12 @@ alone_decode(void *coder_ptr, const lzma_allocator *allocator,
|
||||
}
|
||||
};
|
||||
|
||||
return_if_error(lzma_next_filter_init(&coder->next,
|
||||
allocator, filters));
|
||||
const lzma_ret ret = lzma_next_filter_init(&coder->next,
|
||||
allocator, filters);
|
||||
if (ret != LZMA_OK) {
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
return ret;
|
||||
}
|
||||
|
||||
coder->sequence = SEQ_CODE;
|
||||
break;
|
||||
|
||||
@@ -438,7 +438,8 @@ file_info_decode(void *coder_ptr, const lzma_allocator *allocator,
|
||||
return_if_error(lzma_index_decoder_init(
|
||||
&coder->index_decoder, allocator,
|
||||
&coder->this_index,
|
||||
coder->memlimit - memused));
|
||||
coder->memlimit - memused,
|
||||
coder->footer_flags.backward_size));
|
||||
|
||||
coder->index_remaining = coder->footer_flags.backward_size;
|
||||
coder->sequence = SEQ_INDEX_DECODE;
|
||||
@@ -717,6 +718,13 @@ file_info_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
|
||||
}
|
||||
}
|
||||
|
||||
// combined_index_memusage + this_index_memusage shouldn't overflow
|
||||
// because combined_index_memusage is limited by how much can be
|
||||
// successfully allocated, and this_index_memusage is limited by the
|
||||
// input_size_max check in index_decoder.c. Check for overflow anyway.
|
||||
if (UINT64_MAX - combined_index_memusage < this_index_memusage)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Now we know the total memory usage/requirement. If we had neither
|
||||
// old Indexes nor a new Index, this will be zero which isn't
|
||||
// acceptable as lzma_memusage() has to return non-zero on success
|
||||
|
||||
+172
-92
@@ -14,6 +14,14 @@
|
||||
#include "stream_flags_common.h"
|
||||
|
||||
|
||||
/// \brief Maximum number of Streams supported in lzma_index
|
||||
///
|
||||
/// The maximum number of Streams is UINT32_MAX, because index_tree.count
|
||||
/// is uint32_t. This is unlikely to be reached in practice because it
|
||||
/// would require allocating hundreds of gigabytes of memory.
|
||||
#define STREAMS_MAX UINT32_MAX
|
||||
|
||||
|
||||
/// \brief How many Records to allocate at once
|
||||
///
|
||||
/// This should be big enough to avoid making lots of tiny allocations
|
||||
@@ -28,12 +36,14 @@
|
||||
/// \brief Base structure for index_stream and index_group structures
|
||||
typedef struct index_tree_node_s index_tree_node;
|
||||
struct index_tree_node_s {
|
||||
/// Uncompressed start offset of this Stream (relative to the
|
||||
/// beginning of the file) or Block (relative to the beginning
|
||||
/// of the Stream)
|
||||
/// Uncompressed start offset of this Stream (relative to
|
||||
/// lzma_index.uncompressed_bias) or Block (relative to
|
||||
/// the beginning of the Stream)
|
||||
lzma_vli uncompressed_base;
|
||||
|
||||
/// Compressed start offset of this Stream or Block
|
||||
/// Compressed start offset of this Stream (relative to
|
||||
/// lzma_index.compressed_bias) or Block (relative to
|
||||
/// the beginning of the Stream)
|
||||
lzma_vli compressed_base;
|
||||
|
||||
index_tree_node *parent;
|
||||
@@ -47,13 +57,10 @@ typedef struct {
|
||||
/// Root node
|
||||
index_tree_node *root;
|
||||
|
||||
/// Leftmost node. Since the tree will be filled sequentially,
|
||||
/// this won't change after the first node has been added to
|
||||
/// the tree.
|
||||
/// Leftmost (first) node
|
||||
index_tree_node *leftmost;
|
||||
|
||||
/// The rightmost node in the tree. Since the tree is filled
|
||||
/// sequentially, this is always the node where to add the new data.
|
||||
/// Rightmost (last) node
|
||||
index_tree_node *rightmost;
|
||||
|
||||
/// Number of nodes in the tree
|
||||
@@ -108,10 +115,14 @@ typedef struct {
|
||||
/// Every index_stream is a node in the tree of Streams.
|
||||
index_tree_node node;
|
||||
|
||||
/// Number of this Stream (first one is 1)
|
||||
/// Number of this Stream counted in reverse: the last Stream
|
||||
/// in the lzma_index has .number == 0. In the API, the first
|
||||
/// Stream is 1, so the real number of this Stream is
|
||||
/// lzma_index.streams.count - .number.
|
||||
uint32_t number;
|
||||
|
||||
/// Total number of Blocks before this Stream
|
||||
/// Total number of Blocks before this Stream relative to
|
||||
/// lzma_index.block_number_base.
|
||||
lzma_vli block_number_base;
|
||||
|
||||
/// Record groups of this Stream are stored in a tree.
|
||||
@@ -148,6 +159,15 @@ struct lzma_index_s {
|
||||
/// are many concatenated Streams.
|
||||
index_tree streams;
|
||||
|
||||
/// In index_stream, node.uncompressed_base, node.compressed_base,
|
||||
/// and block_number_base are relative to these _bias members
|
||||
/// instead of being relative to 0. If a new index_stream is
|
||||
/// prepended before the existing index_streams, the offsets of all
|
||||
/// existing index_streams can be changed by updating these _biases.
|
||||
lzma_vli uncompressed_bias;
|
||||
lzma_vli compressed_bias;
|
||||
lzma_vli block_number_bias;
|
||||
|
||||
/// Uncompressed size of all the Blocks in the Stream(s)
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
@@ -226,10 +246,13 @@ index_tree_end(index_tree *tree, const lzma_allocator *allocator,
|
||||
|
||||
/// Add a new node to the tree. node->uncompressed_base and
|
||||
/// node->compressed_base must have been set by the caller already.
|
||||
///
|
||||
/// The tree is always filled sequentially: index_streams are prepended
|
||||
/// and index_groups are appended.
|
||||
static void
|
||||
index_tree_append(index_tree *tree, index_tree_node *node)
|
||||
index_tree_append(index_tree *tree, index_tree_node *node, bool prepend)
|
||||
{
|
||||
node->parent = tree->rightmost;
|
||||
node->parent = prepend ? tree->leftmost : tree->rightmost;
|
||||
node->left = NULL;
|
||||
node->right = NULL;
|
||||
|
||||
@@ -243,14 +266,22 @@ index_tree_append(index_tree *tree, index_tree_node *node)
|
||||
return;
|
||||
}
|
||||
|
||||
// The tree is always filled sequentially.
|
||||
assert(tree->rightmost->uncompressed_base <= node->uncompressed_base);
|
||||
assert(tree->rightmost->compressed_base < node->compressed_base);
|
||||
|
||||
// Add the new node after the rightmost node. It's the correct
|
||||
// place due to the reason above.
|
||||
tree->rightmost->right = node;
|
||||
tree->rightmost = node;
|
||||
// Add the new node before the leftmost or after the rightmost node.
|
||||
if (prepend) {
|
||||
assert(tree->leftmost->uncompressed_base
|
||||
>= node->uncompressed_base);
|
||||
assert(tree->leftmost->compressed_base
|
||||
> node->compressed_base);
|
||||
tree->leftmost->left = node;
|
||||
tree->leftmost = node;
|
||||
} else {
|
||||
assert(tree->rightmost->uncompressed_base
|
||||
<= node->uncompressed_base);
|
||||
assert(tree->rightmost->compressed_base
|
||||
< node->compressed_base);
|
||||
tree->rightmost->right = node;
|
||||
tree->rightmost = node;
|
||||
}
|
||||
|
||||
// Balance the AVL-tree if needed. We don't need to keep the balance
|
||||
// factors in nodes, because we always fill the tree sequentially,
|
||||
@@ -265,11 +296,14 @@ index_tree_append(index_tree *tree, index_tree_node *node)
|
||||
node = node->parent;
|
||||
} while (--up > 0);
|
||||
|
||||
// Rotate left using node as the rotation root.
|
||||
index_tree_node *pivot = node->right;
|
||||
// Rotate right/left using node as the rotation root.
|
||||
index_tree_node *pivot = prepend ? node->left : node->right;
|
||||
|
||||
if (node->parent == NULL) {
|
||||
tree->root = pivot;
|
||||
} else if (prepend) {
|
||||
assert(node->parent->left == node);
|
||||
node->parent->left = pivot;
|
||||
} else {
|
||||
assert(node->parent->right == node);
|
||||
node->parent->right = pivot;
|
||||
@@ -277,11 +311,20 @@ index_tree_append(index_tree *tree, index_tree_node *node)
|
||||
|
||||
pivot->parent = node->parent;
|
||||
|
||||
node->right = pivot->left;
|
||||
if (node->right != NULL)
|
||||
node->right->parent = node;
|
||||
if (prepend) {
|
||||
node->left = pivot->right;
|
||||
if (node->left != NULL)
|
||||
node->left->parent = node;
|
||||
|
||||
pivot->right = node;
|
||||
} else {
|
||||
node->right = pivot->left;
|
||||
if (node->right != NULL)
|
||||
node->right->parent = node;
|
||||
|
||||
pivot->left = node;
|
||||
}
|
||||
|
||||
pivot->left = node;
|
||||
node->parent = pivot;
|
||||
}
|
||||
|
||||
@@ -308,6 +351,25 @@ index_tree_next(const index_tree_node *node)
|
||||
}
|
||||
|
||||
|
||||
/// Get the previous node in the tree. Return NULL if there are no more nodes.
|
||||
static void *
|
||||
index_tree_prev(const index_tree_node *node)
|
||||
{
|
||||
if (node->left != NULL) {
|
||||
node = node->left;
|
||||
while (node->right != NULL)
|
||||
node = node->right;
|
||||
|
||||
return (void *)(node);
|
||||
}
|
||||
|
||||
while (node->parent != NULL && node->parent->left == node)
|
||||
node = node->parent;
|
||||
|
||||
return (void *)(node->parent);
|
||||
}
|
||||
|
||||
|
||||
/// Locate a node that contains the given uncompressed offset. It is
|
||||
/// caller's job to check that target is not bigger than the uncompressed
|
||||
/// size of the tree (the last node would be returned in that case still).
|
||||
@@ -317,9 +379,6 @@ index_tree_locate(const index_tree *tree, lzma_vli target)
|
||||
const index_tree_node *result = NULL;
|
||||
const index_tree_node *node = tree->root;
|
||||
|
||||
assert(tree->leftmost == NULL
|
||||
|| tree->leftmost->uncompressed_base == 0);
|
||||
|
||||
// Consecutive nodes may have the same uncompressed_base.
|
||||
// We must pick the rightmost one.
|
||||
while (node != NULL) {
|
||||
@@ -382,6 +441,9 @@ index_init_plain(const lzma_allocator *allocator)
|
||||
lzma_index *i = lzma_alloc(sizeof(lzma_index), allocator);
|
||||
if (i != NULL) {
|
||||
index_tree_init(&i->streams);
|
||||
i->uncompressed_bias = LZMA_VLI_MAX;
|
||||
i->compressed_bias = LZMA_VLI_MAX;
|
||||
i->block_number_bias = LZMA_VLI_MAX;
|
||||
i->uncompressed_size = 0;
|
||||
i->total_size = 0;
|
||||
i->record_count = 0;
|
||||
@@ -401,13 +463,15 @@ lzma_index_init(const lzma_allocator *allocator)
|
||||
if (i == NULL)
|
||||
return NULL;
|
||||
|
||||
index_stream *s = index_stream_init(0, 0, 1, 0, allocator);
|
||||
index_stream *s = index_stream_init(
|
||||
i->compressed_bias, i->uncompressed_bias,
|
||||
0, i->block_number_bias, allocator);
|
||||
if (s == NULL) {
|
||||
lzma_free(i, allocator);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index_tree_append(&i->streams, &s->node);
|
||||
index_tree_append(&i->streams, &s->node, true);
|
||||
|
||||
return i;
|
||||
}
|
||||
@@ -427,11 +491,11 @@ lzma_index_end(lzma_index *i, const lzma_allocator *allocator)
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
extern bool
|
||||
lzma_index_prealloc(lzma_index *i, lzma_vli records)
|
||||
{
|
||||
if (records > PREALLOC_MAX)
|
||||
records = PREALLOC_MAX;
|
||||
return true;
|
||||
|
||||
// If index_decoder.c calls us with records == 0, it's decoding
|
||||
// an Index that has no Records. In that case the decoder won't call
|
||||
@@ -454,7 +518,7 @@ lzma_index_prealloc(lzma_index *i, lzma_vli records)
|
||||
records = INDEX_GROUP_SIZE;
|
||||
|
||||
i->prealloc = (size_t)(records);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -494,10 +558,8 @@ lzma_index_memusage(lzma_vli streams, lzma_vli blocks)
|
||||
const uint64_t index_base = sizeof(lzma_index) + alloc_overhead;
|
||||
|
||||
// Validate the arguments and catch integer overflows.
|
||||
// Maximum number of Streams is "only" UINT32_MAX, because
|
||||
// that limit is used by the tree containing the Streams.
|
||||
const uint64_t limit = UINT64_MAX - index_base;
|
||||
if (streams == 0 || streams > UINT32_MAX || blocks > LZMA_VLI_MAX
|
||||
if (streams == 0 || streams > STREAMS_MAX || blocks > LZMA_VLI_MAX
|
||||
|| streams > limit / stream_base
|
||||
|| groups > limit / group_base
|
||||
|| limit - streams_mem < groups_mem)
|
||||
@@ -581,7 +643,7 @@ lzma_index_file_size(const lzma_index *i)
|
||||
{
|
||||
const index_stream *s = (const index_stream *)(i->streams.rightmost);
|
||||
const index_group *g = (const index_group *)(s->groups.rightmost);
|
||||
return index_file_size(s->node.compressed_base,
|
||||
return index_file_size(s->node.compressed_base - i->compressed_bias,
|
||||
g == NULL ? 0 : g->records[g->last].unpadded_sum,
|
||||
s->record_count, s->index_list_size,
|
||||
s->stream_padding);
|
||||
@@ -687,7 +749,7 @@ lzma_index_append(lzma_index *i, const lzma_allocator *allocator,
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Check that the file size will stay within limits.
|
||||
if (index_file_size(s->node.compressed_base,
|
||||
if (index_file_size(s->node.compressed_base - i->compressed_bias,
|
||||
compressed_base + unpadded_size, s->record_count + 1,
|
||||
s->index_list_size + index_list_size_add,
|
||||
s->stream_padding) == LZMA_VLI_UNKNOWN)
|
||||
@@ -725,7 +787,7 @@ lzma_index_append(lzma_index *i, const lzma_allocator *allocator,
|
||||
g->number_base = s->record_count + 1;
|
||||
|
||||
// Add the new group to the Stream.
|
||||
index_tree_append(&s->groups, &g->node);
|
||||
index_tree_append(&s->groups, &g->node, false);
|
||||
}
|
||||
|
||||
// Add the new Record to the group.
|
||||
@@ -749,23 +811,11 @@ lzma_index_append(lzma_index *i, const lzma_allocator *allocator,
|
||||
|
||||
/// Structure to pass info to index_cat_helper()
|
||||
typedef struct {
|
||||
/// Uncompressed size of the destination
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Compressed file size of the destination
|
||||
lzma_vli file_size;
|
||||
|
||||
/// Same as above but for Block numbers
|
||||
lzma_vli block_number_add;
|
||||
|
||||
/// Number of Streams that were in the destination index before we
|
||||
/// started appending new Streams from the source index. This is
|
||||
/// used to fix the Stream numbering.
|
||||
uint32_t stream_number_add;
|
||||
|
||||
/// Destination index' Stream tree
|
||||
lzma_vli uncompressed_adjust;
|
||||
lzma_vli compressed_adjust;
|
||||
lzma_vli block_number_adjust;
|
||||
uint32_t stream_number_adjust;
|
||||
index_tree *streams;
|
||||
|
||||
} index_cat_info;
|
||||
|
||||
|
||||
@@ -778,18 +828,19 @@ index_cat_helper(const index_cat_info *info, index_stream *this)
|
||||
index_stream *left = (index_stream *)(this->node.left);
|
||||
index_stream *right = (index_stream *)(this->node.right);
|
||||
|
||||
if (left != NULL)
|
||||
index_cat_helper(info, left);
|
||||
|
||||
this->node.uncompressed_base += info->uncompressed_size;
|
||||
this->node.compressed_base += info->file_size;
|
||||
this->number += info->stream_number_add;
|
||||
this->block_number_base += info->block_number_add;
|
||||
index_tree_append(info->streams, &this->node);
|
||||
|
||||
if (right != NULL)
|
||||
index_cat_helper(info, right);
|
||||
|
||||
// The Stream number counts in reverse, thus += instead of -=.
|
||||
this->node.uncompressed_base -= info->uncompressed_adjust;
|
||||
this->node.compressed_base -= info->compressed_adjust;
|
||||
this->number += info->stream_number_adjust;
|
||||
this->block_number_base -= info->block_number_adjust;
|
||||
index_tree_append(info->streams, &this->node, true);
|
||||
|
||||
if (left != NULL)
|
||||
index_cat_helper(info, left);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -801,6 +852,11 @@ lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
|
||||
if (dest == NULL || src == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Check that we don't exceed the maximum number of Streams
|
||||
// per lzma_index.
|
||||
if (STREAMS_MAX - dest->streams.count < src->streams.count)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
const lzma_vli dest_file_size = lzma_index_file_size(dest);
|
||||
|
||||
// Check that we don't exceed the file size limits.
|
||||
@@ -870,29 +926,39 @@ lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
|
||||
}
|
||||
|
||||
// dest->checks includes the check types of all except the last Stream
|
||||
// in dest. Set the bit for the check type of the last Stream now so
|
||||
// that it won't get lost when Stream(s) from src are appended to dest.
|
||||
dest->checks = lzma_index_checks(dest);
|
||||
// in dest. Use lzma_index_checks() to get the check type of the
|
||||
// last Stream too. This needs to be done before the Streams are
|
||||
// moved from dest to src.
|
||||
src->checks |= lzma_index_checks(dest);
|
||||
|
||||
// Add all the Streams from src to dest. Update the base offsets
|
||||
// of each Stream from src.
|
||||
// Update the biases.
|
||||
src->uncompressed_bias -= dest->uncompressed_size;
|
||||
src->compressed_bias -= dest_file_size;
|
||||
src->block_number_bias -= dest->record_count;
|
||||
|
||||
// Prepend all the Streams from dest to src.
|
||||
const index_cat_info info = {
|
||||
.uncompressed_size = dest->uncompressed_size,
|
||||
.file_size = dest_file_size,
|
||||
.stream_number_add = dest->streams.count,
|
||||
.block_number_add = dest->record_count,
|
||||
.streams = &dest->streams,
|
||||
.uncompressed_adjust = dest->uncompressed_bias
|
||||
- src->uncompressed_bias,
|
||||
.compressed_adjust = dest->compressed_bias
|
||||
- src->compressed_bias,
|
||||
.block_number_adjust = dest->block_number_bias
|
||||
- src->block_number_bias,
|
||||
.stream_number_adjust = src->streams.count,
|
||||
.streams = &src->streams,
|
||||
};
|
||||
index_cat_helper(&info, (index_stream *)(src->streams.root));
|
||||
index_cat_helper(&info, (index_stream *)(dest->streams.root));
|
||||
|
||||
// Update info about all the combined Streams.
|
||||
dest->uncompressed_size += src->uncompressed_size;
|
||||
dest->total_size += src->total_size;
|
||||
dest->record_count += src->record_count;
|
||||
dest->index_list_size += src->index_list_size;
|
||||
dest->checks |= src->checks;
|
||||
src->uncompressed_size += dest->uncompressed_size;
|
||||
src->total_size += dest->total_size;
|
||||
src->record_count += dest->record_count;
|
||||
src->index_list_size += dest->index_list_size;
|
||||
|
||||
// There's nothing else left in src than the base structure.
|
||||
// There's nothing else left in dest than the base structure.
|
||||
// The API is defined so that dest is modified and src is freed,
|
||||
// so copy src to dest and free the base struct of src.
|
||||
*dest = *src;
|
||||
lzma_free(src, allocator);
|
||||
|
||||
return LZMA_OK;
|
||||
@@ -955,7 +1021,7 @@ index_dup_stream(const index_stream *src, const lzma_allocator *allocator)
|
||||
assert(i == destg->allocated);
|
||||
|
||||
// Add the group to the new Stream.
|
||||
index_tree_append(&dest->groups, &destg->node);
|
||||
index_tree_append(&dest->groups, &destg->node, false);
|
||||
|
||||
return dest;
|
||||
}
|
||||
@@ -970,14 +1036,18 @@ lzma_index_dup(const lzma_index *src, const lzma_allocator *allocator)
|
||||
return NULL;
|
||||
|
||||
// Copy the totals.
|
||||
dest->uncompressed_bias = src->uncompressed_bias;
|
||||
dest->compressed_bias = src->compressed_bias;
|
||||
dest->block_number_bias = src->block_number_bias;
|
||||
dest->uncompressed_size = src->uncompressed_size;
|
||||
dest->total_size = src->total_size;
|
||||
dest->record_count = src->record_count;
|
||||
dest->index_list_size = src->index_list_size;
|
||||
dest->checks = src->checks;
|
||||
|
||||
// Copy the Streams and the groups in them.
|
||||
const index_stream *srcstream
|
||||
= (const index_stream *)(src->streams.leftmost);
|
||||
= (const index_stream *)(src->streams.rightmost);
|
||||
do {
|
||||
index_stream *deststream = index_dup_stream(
|
||||
srcstream, allocator);
|
||||
@@ -986,9 +1056,9 @@ lzma_index_dup(const lzma_index *src, const lzma_allocator *allocator)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index_tree_append(&dest->streams, &deststream->node);
|
||||
index_tree_append(&dest->streams, &deststream->node, true);
|
||||
|
||||
srcstream = index_tree_next(&srcstream->node);
|
||||
srcstream = index_tree_prev(&srcstream->node);
|
||||
} while (srcstream != NULL);
|
||||
|
||||
return dest;
|
||||
@@ -1052,11 +1122,14 @@ iter_set_info(lzma_index_iter *iter)
|
||||
}
|
||||
|
||||
// NOTE: lzma_index_iter.stream.number is lzma_vli but we use uint32_t
|
||||
// internally.
|
||||
iter->stream.number = stream->number;
|
||||
// internally. The internal value counts in reverse (last one is 0)
|
||||
// but in lzma_index_iter.stream.number the first Stream is 1.
|
||||
iter->stream.number = i->streams.count - stream->number;
|
||||
iter->stream.block_count = stream->record_count;
|
||||
iter->stream.compressed_offset = stream->node.compressed_base;
|
||||
iter->stream.uncompressed_offset = stream->node.uncompressed_base;
|
||||
iter->stream.compressed_offset = stream->node.compressed_base
|
||||
- i->compressed_bias;
|
||||
iter->stream.uncompressed_offset = stream->node.uncompressed_base
|
||||
- i->uncompressed_bias;
|
||||
|
||||
// iter->stream.flags will be NULL if the Stream Flags haven't been
|
||||
// set with lzma_index_stream_flags().
|
||||
@@ -1085,7 +1158,7 @@ iter_set_info(lzma_index_iter *iter)
|
||||
if (group != NULL) {
|
||||
iter->block.number_in_stream = group->number_base + record;
|
||||
iter->block.number_in_file = iter->block.number_in_stream
|
||||
+ stream->block_number_base;
|
||||
+ (stream->block_number_base - i->block_number_bias);
|
||||
|
||||
iter->block.compressed_stream_offset
|
||||
= record == 0 ? group->node.compressed_base
|
||||
@@ -1250,14 +1323,21 @@ lzma_index_iter_locate(lzma_index_iter *iter, lzma_vli target)
|
||||
{
|
||||
const lzma_index *i = iter->internal[ITER_INDEX].p;
|
||||
|
||||
assert(i->uncompressed_size <= LZMA_VLI_MAX);
|
||||
|
||||
// If the target is past the end of the file, return immediately.
|
||||
if (i->uncompressed_size <= target)
|
||||
return true;
|
||||
|
||||
assert(target < LZMA_VLI_MAX);
|
||||
|
||||
// Locate the Stream containing the target offset.
|
||||
// NOTE: Adding the bias can make target >= LZMA_VLI_MAX.
|
||||
target += i->uncompressed_bias;
|
||||
const index_stream *stream = index_tree_locate(&i->streams, target);
|
||||
assert(stream != NULL);
|
||||
target -= stream->node.uncompressed_base;
|
||||
assert(target < LZMA_VLI_MAX);
|
||||
|
||||
// Locate the group containing the target offset.
|
||||
const index_group *group = index_tree_locate(&stream->groups, target);
|
||||
|
||||
@@ -38,7 +38,9 @@ extern uint32_t lzma_index_padding_size(const lzma_index *i);
|
||||
/// Set for how many Records to allocate memory the next time
|
||||
/// lzma_index_append() needs to allocate space for a new Record.
|
||||
/// This is used only by the Index decoder.
|
||||
extern void lzma_index_prealloc(lzma_index *i, lzma_vli records);
|
||||
///
|
||||
/// \return false on success, true if records is too large (SIZE_MAX issue)
|
||||
extern bool lzma_index_prealloc(lzma_index *i, lzma_vli records);
|
||||
|
||||
|
||||
/// Round the variable-length integer to the next multiple of four.
|
||||
|
||||
@@ -28,6 +28,10 @@ typedef struct {
|
||||
/// Memory usage limit
|
||||
uint64_t memlimit;
|
||||
|
||||
// Memory used for lzma_index once it has been allocated.
|
||||
// Before that, this holds a tiny value.
|
||||
uint64_t memused;
|
||||
|
||||
/// Target Index
|
||||
lzma_index *index;
|
||||
|
||||
@@ -35,6 +39,12 @@ typedef struct {
|
||||
/// successful decoding.
|
||||
lzma_index **index_ptr;
|
||||
|
||||
/// If Number of Records contains a value higher than this,
|
||||
/// the Index is immediately considered to be corrupt.
|
||||
/// This prevents us from allocating a large amount of memory
|
||||
/// when we know that the Index isn't big.
|
||||
lzma_vli number_of_records_max;
|
||||
|
||||
/// Number of Records left to decode.
|
||||
lzma_vli count;
|
||||
|
||||
@@ -91,19 +101,32 @@ index_decode(void *coder_ptr, const lzma_allocator *allocator,
|
||||
if (ret != LZMA_STREAM_END)
|
||||
goto out;
|
||||
|
||||
// Reject Number of Records values that are clearly invalid.
|
||||
if (coder->count > coder->number_of_records_max)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_MEMUSAGE;
|
||||
FALLTHROUGH;
|
||||
|
||||
case SEQ_MEMUSAGE:
|
||||
if (lzma_index_memusage(1, coder->count) > coder->memlimit) {
|
||||
coder->memused = lzma_index_memusage(1, coder->count);
|
||||
|
||||
// We sanity-checked coder->count in SEQ_COUNT, which
|
||||
// guarantees that lzma_index_memusage() won't fail.
|
||||
assert(coder->memused != UINT64_MAX);
|
||||
|
||||
if (coder->memused > coder->memlimit) {
|
||||
ret = LZMA_MEMLIMIT_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Tell the Index handling code how many Records this
|
||||
// Index has to allow it to allocate memory more efficiently.
|
||||
lzma_index_prealloc(coder->index, coder->count);
|
||||
// If the Record count is so high that memory allocation would
|
||||
// fail later, return LZMA_MEM_ERROR now.
|
||||
if (lzma_index_prealloc(coder->index, coder->count))
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
ret = LZMA_OK;
|
||||
coder->sequence = coder->count == 0
|
||||
@@ -230,7 +253,10 @@ index_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
|
||||
{
|
||||
lzma_index_coder *coder = coder_ptr;
|
||||
|
||||
*memusage = lzma_index_memusage(1, coder->count);
|
||||
// Index decoder is special in sense that the returned memusage
|
||||
// doesn't include the memory usage of the decoder itself; only
|
||||
// the resulting lzma_index is counted.
|
||||
*memusage = coder->memused;
|
||||
*old_memlimit = coder->memlimit;
|
||||
|
||||
if (new_memlimit != 0) {
|
||||
@@ -246,7 +272,7 @@ index_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
|
||||
|
||||
static lzma_ret
|
||||
index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
|
||||
lzma_index **i, uint64_t memlimit)
|
||||
lzma_index **i, uint64_t memlimit, uint64_t input_size_max)
|
||||
{
|
||||
// Remember the pointer given by the application. We will set it
|
||||
// to point to the decoded Index only if decoding is successful.
|
||||
@@ -260,10 +286,19 @@ index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
|
||||
if (coder->index == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
// Approximate how many Records the Index may contain at most when
|
||||
// we know that the Index won't be larger than input_size_max bytes.
|
||||
// Each Record must consume at least two bytes. The CRC32 etc.
|
||||
// consume a few bytes too, but we don't need an exact value.
|
||||
//
|
||||
// file_info.c knows Backward Size and passes it to us. When we have
|
||||
// no information, input_size_max equals LZMA_BACKWARD_SIZE_MAX.
|
||||
coder->number_of_records_max = input_size_max / 2;
|
||||
|
||||
// Initialize the rest.
|
||||
coder->sequence = SEQ_INDICATOR;
|
||||
coder->memlimit = my_max(1, memlimit);
|
||||
coder->count = 0; // Needs to be initialized due to _memconfig().
|
||||
coder->memused = 1; // If _memconfig() is called before SEQ_MEMUSAGE.
|
||||
coder->pos = 0;
|
||||
coder->crc32 = 0;
|
||||
|
||||
@@ -273,7 +308,7 @@ index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
|
||||
|
||||
extern lzma_ret
|
||||
lzma_index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
lzma_index **i, uint64_t memlimit)
|
||||
lzma_index **i, uint64_t memlimit, uint64_t input_size_max)
|
||||
{
|
||||
lzma_next_coder_init(&lzma_index_decoder_init, next, allocator);
|
||||
|
||||
@@ -295,7 +330,8 @@ lzma_index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
lzma_index_end(coder->index, allocator);
|
||||
}
|
||||
|
||||
return index_decoder_reset(coder, allocator, i, memlimit);
|
||||
return index_decoder_reset(
|
||||
coder, allocator, i, memlimit, input_size_max);
|
||||
}
|
||||
|
||||
|
||||
@@ -308,7 +344,8 @@ lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
|
||||
if (i != NULL)
|
||||
*i = NULL;
|
||||
|
||||
lzma_next_strm_init(lzma_index_decoder_init, strm, i, memlimit);
|
||||
lzma_next_strm_init(lzma_index_decoder_init, strm, i, memlimit,
|
||||
LZMA_BACKWARD_SIZE_MAX);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
@@ -334,7 +371,9 @@ lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
|
||||
|
||||
// Initialize the decoder.
|
||||
lzma_index_coder coder;
|
||||
return_if_error(index_decoder_reset(&coder, allocator, i, *memlimit));
|
||||
const uint64_t input_size_max = in_size - *in_pos;
|
||||
return_if_error(index_decoder_reset(&coder, allocator, i, *memlimit,
|
||||
my_min(input_size_max, LZMA_BACKWARD_SIZE_MAX)));
|
||||
|
||||
// Store the input start position so that we can restore it in case
|
||||
// of an error.
|
||||
@@ -361,7 +400,7 @@ lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
|
||||
} else if (ret == LZMA_MEMLIMIT_ERROR) {
|
||||
// Tell the caller how much memory would have
|
||||
// been needed.
|
||||
*memlimit = lzma_index_memusage(1, coder.count);
|
||||
*memlimit = coder.memused;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
extern lzma_ret lzma_index_decoder_init(lzma_next_coder *next,
|
||||
const lzma_allocator *allocator,
|
||||
lzma_index **i, uint64_t memlimit);
|
||||
lzma_index **i, uint64_t memlimit, uint64_t input_size_max);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -237,8 +237,12 @@ lzip_decode(void *coder_ptr, const lzma_allocator *allocator,
|
||||
}
|
||||
};
|
||||
|
||||
return_if_error(lzma_next_filter_init(&coder->lzma_decoder,
|
||||
allocator, filters));
|
||||
const lzma_ret ret = lzma_next_filter_init(
|
||||
&coder->lzma_decoder, allocator, filters);
|
||||
if (ret != LZMA_OK) {
|
||||
lzma_next_end(&coder->lzma_decoder, allocator);
|
||||
return ret;
|
||||
}
|
||||
|
||||
coder->crc32 = 0;
|
||||
coder->sequence = SEQ_LZMA_STREAM;
|
||||
|
||||
@@ -108,8 +108,12 @@ microlzma_decode(void *coder_ptr, const lzma_allocator *allocator,
|
||||
}
|
||||
};
|
||||
|
||||
return_if_error(lzma_next_filter_init(&coder->lzma,
|
||||
allocator, filters));
|
||||
const lzma_ret ret = lzma_next_filter_init(&coder->lzma,
|
||||
allocator, filters);
|
||||
if (ret != LZMA_OK) {
|
||||
lzma_next_end(&coder->lzma, allocator);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Pass one dummy 0x00 byte to the LZMA decoder since that
|
||||
// is what it expects the first byte to be.
|
||||
|
||||
@@ -50,10 +50,6 @@ lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags,
|
||||
if (ret == LZMA_STREAM_END) {
|
||||
ret = LZMA_OK;
|
||||
} else {
|
||||
// Something went wrong, restore the positions.
|
||||
*in_pos = in_start;
|
||||
*out_pos = out_start;
|
||||
|
||||
if (ret == LZMA_OK) {
|
||||
// Either the input was truncated or the
|
||||
// output buffer was too small.
|
||||
@@ -78,6 +74,10 @@ lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags,
|
||||
stream_decoder.coder,
|
||||
memlimit, &memusage, 0);
|
||||
}
|
||||
|
||||
// Something went wrong, restore the positions.
|
||||
*in_pos = in_start;
|
||||
*out_pos = out_start;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -250,13 +250,13 @@ struct lzma_stream_coder {
|
||||
/// Amount of compressed data in Stream Header + Blocks that have
|
||||
/// already been finished.
|
||||
///
|
||||
/// \note Use mutex.
|
||||
/// \note Use mutex when worker threads might be active.
|
||||
uint64_t progress_in;
|
||||
|
||||
/// Amount of uncompressed data in Blocks that have already
|
||||
/// been finished.
|
||||
///
|
||||
/// \note Use mutex.
|
||||
/// \note Use mutex when worker threads might be active.
|
||||
uint64_t progress_out;
|
||||
|
||||
|
||||
@@ -1068,7 +1068,12 @@ stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator,
|
||||
const size_t in_old = *in_pos;
|
||||
const lzma_ret ret = decode_block_header(coder, allocator,
|
||||
in, in_pos, in_size);
|
||||
coder->progress_in += *in_pos - in_old;
|
||||
|
||||
// Worker threads may finish earlier Blocks and need to update
|
||||
// coder->progress_in at the same time with us.
|
||||
mythread_sync(coder->mutex) {
|
||||
coder->progress_in += *in_pos - in_old;
|
||||
}
|
||||
|
||||
if (ret == LZMA_OK) {
|
||||
// We didn't decode the whole Block Header yet.
|
||||
|
||||
@@ -278,6 +278,7 @@ lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
|
||||
// Allocate and initialize the dictionary.
|
||||
if (coder->dict.size != alloc_size) {
|
||||
coder->dict.size = 0;
|
||||
lzma_free(coder->dict.buf, allocator);
|
||||
|
||||
// The LZ_DICT_EXTRA bytes at the end of the buffer aren't
|
||||
|
||||
@@ -165,11 +165,32 @@ lzma2_decode(void *coder_ptr, lzma_dict *restrict dict,
|
||||
// coder->compressed_size later.
|
||||
const size_t in_start = *in_pos;
|
||||
|
||||
// LZMA2 stream ends with the end marker (0x00), so there
|
||||
// must be at least one byte after this chunk. Let the
|
||||
// decoder read at most one byte past the end of the chunk.
|
||||
// If the decoder reads the extra byte, then the input is
|
||||
// corrupt. This way we won't produce (much) junk output
|
||||
// from the input bytes that are past the end of this chunk.
|
||||
// The extra byte makes things simpler, because we can ignore
|
||||
// uncompressed size and not think about some corner cases.
|
||||
//
|
||||
// NOTE: It's not a security issue (information leak) to
|
||||
// pass more input to the decoder than the chunk size.
|
||||
// If an attacker can modify the compressed input, then the
|
||||
// attacker can modify a chunk header so that it specifies
|
||||
// a too large compressed size. liblzma <= 5.8.3 didn't
|
||||
// have in_limit; in_size was passed to the decoder as is.
|
||||
const size_t in_limit = *in_pos + my_min(in_size - *in_pos,
|
||||
coder->compressed_size + 1);
|
||||
|
||||
// Decode from in[] to *dict.
|
||||
const lzma_ret ret = coder->lzma.code(coder->lzma.coder,
|
||||
dict, in, in_pos, in_size);
|
||||
dict, in, in_pos, in_limit);
|
||||
|
||||
// Validate and update coder->compressed_size.
|
||||
// Validate and update coder->compressed_size. If the input
|
||||
// is corrupt, let the caller still see the newly-decoded
|
||||
// output even if it is (partially) corrupt. It might allow
|
||||
// users to recover a small amount of useful data.
|
||||
const size_t in_used = *in_pos - in_start;
|
||||
if (in_used > coder->compressed_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
@@ -252,6 +252,17 @@ lzma_simple_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
// Allocate memory for the filter-specific data structure.
|
||||
if (simple_size > 0) {
|
||||
coder->simple = lzma_alloc(simple_size, allocator);
|
||||
if (coder->simple == NULL) {
|
||||
lzma_free(coder, allocator);
|
||||
return LZMA_MEM_ERROR;
|
||||
}
|
||||
} else {
|
||||
coder->simple = NULL;
|
||||
}
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &simple_code;
|
||||
next->end = &simple_coder_end;
|
||||
@@ -260,15 +271,6 @@ lzma_simple_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
coder->next = LZMA_NEXT_CODER_INIT;
|
||||
coder->filter = filter;
|
||||
coder->allocated = 2 * unfiltered_max;
|
||||
|
||||
// Allocate memory for filter-specific data structure.
|
||||
if (simple_size > 0) {
|
||||
coder->simple = lzma_alloc(simple_size, allocator);
|
||||
if (coder->simple == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
} else {
|
||||
coder->simple = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (filters[0].options != NULL) {
|
||||
|
||||
+21
-12
@@ -75,7 +75,8 @@ parse_block_list(const char *str_const)
|
||||
|
||||
// It must be non-empty and not begin with a comma.
|
||||
if (str[0] == '\0' || str[0] == ',')
|
||||
message_fatal(_("%s: Invalid argument to --block-list"), str);
|
||||
message_fatal(_("%s: Invalid argument to --block-list"),
|
||||
tuklib_mask_nonprint(str));
|
||||
|
||||
// Count the number of comma-separated strings.
|
||||
size_t count = 1;
|
||||
@@ -86,7 +87,7 @@ parse_block_list(const char *str_const)
|
||||
// Prevent an unlikely integer overflow.
|
||||
if (count > SIZE_MAX / sizeof(block_list_entry) - 1)
|
||||
message_fatal(_("%s: Too many arguments to --block-list"),
|
||||
str);
|
||||
tuklib_mask_nonprint(str));
|
||||
|
||||
// Allocate memory to hold all the sizes specified.
|
||||
// If --block-list was specified already, its value is forgotten.
|
||||
@@ -562,7 +563,8 @@ parse_real(args_info *args, int argc, char **argv)
|
||||
if (++i == ARRAY_SIZE(types))
|
||||
message_fatal(_("%s: Unknown file "
|
||||
"format type"),
|
||||
optarg);
|
||||
tuklib_mask_nonprint(
|
||||
optarg));
|
||||
|
||||
opt_format = types[i].format;
|
||||
break;
|
||||
@@ -584,15 +586,16 @@ parse_real(args_info *args, int argc, char **argv)
|
||||
while (strcmp(types[i].str, optarg) != 0) {
|
||||
if (++i == ARRAY_SIZE(types))
|
||||
message_fatal(_("%s: Unsupported "
|
||||
"integrity "
|
||||
"check type"), optarg);
|
||||
"integrity check type"),
|
||||
tuklib_mask_nonprint(optarg));
|
||||
}
|
||||
|
||||
// Use a separate check in case we are using different
|
||||
// liblzma than what was used to compile us.
|
||||
if (!lzma_check_is_supported(types[i].check))
|
||||
message_fatal(_("%s: Unsupported integrity "
|
||||
"check type"), optarg);
|
||||
message_fatal(_("%s: Unsupported "
|
||||
"integrity check type"),
|
||||
tuklib_mask_nonprint(optarg));
|
||||
|
||||
coder_set_check(types[i].check);
|
||||
break;
|
||||
@@ -635,18 +638,24 @@ parse_real(args_info *args, int argc, char **argv)
|
||||
"or '--files0'."));
|
||||
|
||||
if (optarg == NULL) {
|
||||
args->files_name = stdin_filename;
|
||||
args->files_name = (char *)stdin_filename;
|
||||
args->files_file = stdin;
|
||||
} else {
|
||||
args->files_name = optarg;
|
||||
args->files_file = fopen(optarg,
|
||||
// If we are called from parse_environment(),
|
||||
// the memory pointed by optarg will be freed
|
||||
// after we return to parse_environment().
|
||||
// We need to duplicate the string.
|
||||
args->files_name = xstrdup(optarg);
|
||||
args->files_file = fopen(args->files_name,
|
||||
c == OPT_FILES ? "r" : "rb");
|
||||
if (args->files_file == NULL)
|
||||
// TRANSLATORS: This is a translatable
|
||||
// string because French needs a space
|
||||
// before the colon ("%s : %s").
|
||||
message_fatal(_("%s: %s"), optarg,
|
||||
strerror(errno));
|
||||
message_fatal(_("%s: %s"),
|
||||
tuklib_mask_nonprint(
|
||||
args->files_name),
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ typedef struct {
|
||||
|
||||
/// Name of the file from which to read filenames. This is NULL
|
||||
/// if --files or --files0 was not used.
|
||||
const char *files_name;
|
||||
char *files_name;
|
||||
|
||||
/// File opened for reading from which filenames are read. This is
|
||||
/// non-NULL only if files_name is non-NULL.
|
||||
|
||||
+1
-1
@@ -172,7 +172,7 @@ str_to_filters(const char *str, uint32_t index, uint32_t flags)
|
||||
// the messages are included in xz's translations.
|
||||
message(V_ERROR, _("Error in --filters%s=FILTERS option:"),
|
||||
filter_num);
|
||||
message(V_ERROR, "%s", str);
|
||||
message(V_ERROR, "%s", tuklib_mask_nonprint(str));
|
||||
message(V_ERROR, "%*s^", error_pos, "");
|
||||
message_fatal("%s", _(err));
|
||||
}
|
||||
|
||||
+29
-5
@@ -1142,12 +1142,36 @@ print_info_robot(xz_file_info *xfi, file_pair *pair)
|
||||
static void
|
||||
update_totals(const xz_file_info *xfi)
|
||||
{
|
||||
// TODO: Integer overflow checks
|
||||
const uint64_t streams = lzma_index_stream_count(xfi->idx);
|
||||
const uint64_t blocks = lzma_index_block_count(xfi->idx);
|
||||
const uint64_t compressed_size = lzma_index_file_size(xfi->idx);
|
||||
const uint64_t uncompressed_size
|
||||
= lzma_index_uncompressed_size(xfi->idx);
|
||||
|
||||
// Of these, totals.uncompressed_size is the most likely to overflow
|
||||
// because it doesn't require a huge file. Even that is likely to
|
||||
// happen only with invalid/crafted files.
|
||||
//
|
||||
// For simplicity, the error message refers to file sizes even though
|
||||
// we are checking other things too.
|
||||
if (totals.files == UINT64_MAX
|
||||
|| UINT64_MAX - totals.streams < streams
|
||||
|| UINT64_MAX - totals.blocks < blocks
|
||||
|| UINT64_MAX - totals.compressed_size
|
||||
< compressed_size
|
||||
|| UINT64_MAX - totals.uncompressed_size
|
||||
< uncompressed_size
|
||||
|| UINT64_MAX - totals.stream_padding
|
||||
< xfi->stream_padding) {
|
||||
message_fatal(_("Error: The total compressed or uncompressed "
|
||||
"size of the files is too large"));
|
||||
}
|
||||
|
||||
++totals.files;
|
||||
totals.streams += lzma_index_stream_count(xfi->idx);
|
||||
totals.blocks += lzma_index_block_count(xfi->idx);
|
||||
totals.compressed_size += lzma_index_file_size(xfi->idx);
|
||||
totals.uncompressed_size += lzma_index_uncompressed_size(xfi->idx);
|
||||
totals.streams += streams;
|
||||
totals.blocks += blocks;
|
||||
totals.compressed_size += compressed_size;
|
||||
totals.uncompressed_size += uncompressed_size;
|
||||
totals.stream_padding += xfi->stream_padding;
|
||||
totals.checks |= lzma_index_checks(xfi->idx);
|
||||
|
||||
|
||||
+8
-4
@@ -89,7 +89,7 @@ read_name(const args_info *args)
|
||||
message_error(_("%s: Error reading filenames: %s"),
|
||||
tuklib_mask_nonprint(args->files_name),
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (feof(args->files_file)) {
|
||||
@@ -99,7 +99,7 @@ read_name(const args_info *args)
|
||||
tuklib_mask_nonprint(
|
||||
args->files_name));
|
||||
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == args->files_delim) {
|
||||
@@ -125,7 +125,7 @@ read_name(const args_info *args)
|
||||
"of '--files'?"),
|
||||
tuklib_mask_nonprint(
|
||||
args->files_name));
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
name[pos++] = c;
|
||||
@@ -149,6 +149,8 @@ read_name(const args_info *args)
|
||||
}
|
||||
}
|
||||
|
||||
free(name);
|
||||
name = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -335,8 +337,10 @@ main(int argc, char **argv)
|
||||
run(name);
|
||||
}
|
||||
|
||||
if (args.files_name != stdin_filename)
|
||||
if (args.files_name != stdin_filename) {
|
||||
(void)fclose(args.files_file);
|
||||
free(args.files_name);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_DECODERS
|
||||
|
||||
+8
-1
@@ -650,7 +650,14 @@ progress_flush(bool finished)
|
||||
cols[4]);
|
||||
} else {
|
||||
// The filename is always printed.
|
||||
fprintf(stderr, _("%s: "), tuklib_mask_nonprint(filename));
|
||||
//
|
||||
// NOTE: This function is called from vmessage() whose
|
||||
// caller may have used tuklib_mask_nonprint(). Thus,
|
||||
// we must use the _r variant here.
|
||||
char *mem = NULL;
|
||||
fprintf(stderr, _("%s: "),
|
||||
tuklib_mask_nonprint_r(filename, &mem));
|
||||
free(mem);
|
||||
|
||||
// Percentage is printed only if we didn't finish yet.
|
||||
if (!finished) {
|
||||
|
||||
+2
-2
@@ -111,7 +111,7 @@ str_to_uint64(const char *name, const char *value, uint64_t min, uint64_t max)
|
||||
return max;
|
||||
|
||||
if (*value < '0' || *value > '9')
|
||||
message_fatal(_("%s: %s"), value,
|
||||
message_fatal(_("%s: %s"), tuklib_mask_nonprint(value),
|
||||
_("Value is not a non-negative decimal integer"));
|
||||
|
||||
do {
|
||||
@@ -154,7 +154,7 @@ str_to_uint64(const char *name, const char *value, uint64_t min, uint64_t max)
|
||||
|
||||
if (multiplier == 0) {
|
||||
message(V_ERROR, _("%s: Invalid multiplier suffix"),
|
||||
value - 1);
|
||||
tuklib_mask_nonprint(value - 1));
|
||||
message_fatal(_("Valid suffixes are 'KiB' (2^10), "
|
||||
"'MiB' (2^20), and 'GiB' (2^30)."));
|
||||
}
|
||||
|
||||
+76
-82
@@ -353,7 +353,7 @@ the command name (for example,
|
||||
.B unxz
|
||||
implies
|
||||
.BR \-\-decompress ).
|
||||
.IP ""
|
||||
.IP
|
||||
.\" The DESCRIPTION section already says this but it's good to repeat it
|
||||
.\" here because the default behavior is a bit dangerous and new users
|
||||
.\" in a hurry may skip reading the DESCRIPTION section.
|
||||
@@ -389,7 +389,7 @@ and no files are created or removed.
|
||||
In list mode, the program cannot read
|
||||
the compressed data from standard
|
||||
input or from other unseekable sources.
|
||||
.IP ""
|
||||
.IP
|
||||
The default listing shows basic information about
|
||||
.IR files ,
|
||||
one file per line.
|
||||
@@ -404,7 +404,7 @@ The width of verbose output exceeds
|
||||
80 characters, so piping the output to, for example,
|
||||
.B "less\ \-S"
|
||||
may be convenient if the terminal isn't wide enough.
|
||||
.IP ""
|
||||
.IP
|
||||
The exact output may vary between
|
||||
.B xz
|
||||
versions and different locales.
|
||||
@@ -416,7 +416,7 @@ should be used.
|
||||
.TP
|
||||
.BR \-k ", " \-\-keep
|
||||
Don't delete the input files.
|
||||
.IP ""
|
||||
.IP
|
||||
Since
|
||||
.B xz
|
||||
5.2.6,
|
||||
@@ -485,7 +485,7 @@ silently ignore possible remaining input data following the stream.
|
||||
Normally such trailing garbage makes
|
||||
.B xz
|
||||
display an error.
|
||||
.IP ""
|
||||
.IP
|
||||
.B xz
|
||||
never decompresses more than one stream from
|
||||
.B .lzma
|
||||
@@ -494,12 +494,12 @@ files or raw streams, but this option still makes
|
||||
ignore the possible trailing data after the
|
||||
.B .lzma
|
||||
file or raw stream.
|
||||
.IP ""
|
||||
.IP
|
||||
This option has no effect if the operation mode is not
|
||||
.B \-\-decompress
|
||||
or
|
||||
.BR \-\-test .
|
||||
.IP ""
|
||||
.IP
|
||||
Since
|
||||
.B xz
|
||||
5.7.1alpha,
|
||||
@@ -530,7 +530,7 @@ If not writing to standard output and
|
||||
the source file already has the suffix
|
||||
.IR .suf ,
|
||||
a warning is displayed and the file is skipped.
|
||||
.IP ""
|
||||
.IP
|
||||
When decompressing, recognize files with the suffix
|
||||
.I .suf
|
||||
in addition to files with the
|
||||
@@ -544,7 +544,7 @@ suffix.
|
||||
If the source file has the suffix
|
||||
.IR .suf ,
|
||||
the suffix is removed to get the target filename.
|
||||
.IP ""
|
||||
.IP
|
||||
When compressing or decompressing raw streams
|
||||
.RB ( \-\-format=raw ),
|
||||
the suffix must always be specified unless
|
||||
@@ -612,7 +612,7 @@ Accept only
|
||||
.B .lz
|
||||
files when decompressing.
|
||||
Compression is not supported.
|
||||
.IP ""
|
||||
.IP
|
||||
The
|
||||
.B .lz
|
||||
format versions 0 and 1 are supported.
|
||||
@@ -651,7 +651,7 @@ format doesn't support integrity checks.
|
||||
The integrity check (if any) is verified when the
|
||||
.B .xz
|
||||
file is decompressed.
|
||||
.IP ""
|
||||
.IP
|
||||
Supported
|
||||
.I check
|
||||
types:
|
||||
@@ -678,7 +678,7 @@ at detecting damaged files and the speed difference is negligible.
|
||||
Calculate SHA-256.
|
||||
This is somewhat slower than CRC32 and CRC64.
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
Integrity of the
|
||||
.B .xz
|
||||
headers is always verified with CRC32.
|
||||
@@ -689,7 +689,7 @@ Don't verify the integrity check of the compressed data when decompressing.
|
||||
The CRC32 values in the
|
||||
.B .xz
|
||||
headers will still be verified normally.
|
||||
.IP ""
|
||||
.IP
|
||||
.B "Do not use this option unless you know what you are doing."
|
||||
Possible reasons to use this option:
|
||||
.RS
|
||||
@@ -711,7 +711,7 @@ If multiple preset levels are specified,
|
||||
the last one takes effect.
|
||||
If a custom filter chain was already specified, setting
|
||||
a compression preset level clears the custom filter chain.
|
||||
.IP ""
|
||||
.IP
|
||||
The differences between the presets are more significant than with
|
||||
.BR gzip (1)
|
||||
and
|
||||
@@ -761,17 +761,16 @@ but with higher compressor and decompressor memory requirements.
|
||||
These are useful only when compressing files bigger than
|
||||
8\ MiB, 16\ MiB, and 32\ MiB, respectively.
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
On the same hardware, the decompression speed is approximately
|
||||
a constant number of bytes of compressed data per second.
|
||||
In other words, the better the compression,
|
||||
the faster the decompression will usually be.
|
||||
This also means that the amount of uncompressed output
|
||||
produced per second can vary a lot.
|
||||
.IP ""
|
||||
.IP
|
||||
The following table summarises the features of the presets:
|
||||
.RS
|
||||
.RS
|
||||
.PP
|
||||
.TS
|
||||
tab(;);
|
||||
@@ -790,8 +789,7 @@ Preset;DictSize;CompCPU;CompMem;DecMem
|
||||
\-9;64 MiB;6;674 MiB;65 MiB
|
||||
.TE
|
||||
.RE
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
Column descriptions:
|
||||
.RS
|
||||
.IP \(bu 3
|
||||
@@ -828,7 +826,7 @@ The exact decompressor memory usage is slightly more than
|
||||
the LZMA2 dictionary size, but the values in the table
|
||||
have been rounded up to the next full MiB.
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
Memory requirements of the multi-threaded mode are
|
||||
significantly higher than that of the single-threaded mode.
|
||||
With the default value of
|
||||
@@ -846,7 +844,7 @@ but with bad luck this can also make it worse.
|
||||
Decompressor memory usage is not affected,
|
||||
but compressor memory usage increases a little at preset levels
|
||||
.BR \-0 " ... " \-3 .
|
||||
.IP ""
|
||||
.IP
|
||||
Since there are two presets with dictionary sizes
|
||||
4\ MiB and 8\ MiB, the presets
|
||||
.B \-3e
|
||||
@@ -859,7 +857,6 @@ and
|
||||
respectively.
|
||||
That way no two presets are identical.
|
||||
.RS
|
||||
.RS
|
||||
.PP
|
||||
.TS
|
||||
tab(;);
|
||||
@@ -878,8 +875,7 @@ Preset;DictSize;CompCPU;CompMem;DecMem
|
||||
\-9e;64 MiB;8;674 MiB;65 MiB
|
||||
.TE
|
||||
.RE
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
For example, there are a total of four presets that use
|
||||
8\ MiB dictionary, whose order from the fastest to the slowest is
|
||||
.BR \-5 ,
|
||||
@@ -914,7 +910,7 @@ makes limited random-access decompression possible.
|
||||
This option is typically used to override the default
|
||||
block size in multi-threaded mode,
|
||||
but this option can be used in single-threaded mode too.
|
||||
.IP ""
|
||||
.IP
|
||||
In multi-threaded mode about three times
|
||||
.I size
|
||||
bytes will be allocated in each thread for buffering input and output.
|
||||
@@ -931,7 +927,7 @@ because then the LZMA2 dictionary buffer will never get fully used.
|
||||
In multi-threaded mode,
|
||||
the sizes of the blocks are stored in the block headers.
|
||||
This size information is required for multi-threaded decompression.
|
||||
.IP ""
|
||||
.IP
|
||||
In single-threaded mode no block splitting is done by default.
|
||||
Setting this option doesn't affect memory usage.
|
||||
No size information is stored in block headers,
|
||||
@@ -946,7 +942,7 @@ When compressing to the
|
||||
.B .xz
|
||||
format, start a new block with an optional custom filter chain after
|
||||
the given intervals of uncompressed data.
|
||||
.IP ""
|
||||
.IP
|
||||
The
|
||||
.I items
|
||||
are a comma-separated list.
|
||||
@@ -956,7 +952,7 @@ between 0 and 9 followed by a colon
|
||||
and a required size of uncompressed data.
|
||||
Omitting an item (two or more consecutive commas) is a
|
||||
shorthand to use the size and filters of the previous item.
|
||||
.IP ""
|
||||
.IP
|
||||
If the input file is bigger than the sum of
|
||||
the sizes in
|
||||
.IR items ,
|
||||
@@ -965,7 +961,7 @@ A special value of
|
||||
.B 0
|
||||
may be used as the last size to indicate that
|
||||
the rest of the file should be encoded as a single block.
|
||||
.IP ""
|
||||
.IP
|
||||
An alternative filter chain for each block can be
|
||||
specified in combination with the
|
||||
.BI \-\-filters1= filters
|
||||
@@ -1005,7 +1001,7 @@ The default filter chain and 2 MiB input
|
||||
The default filter chain and 4 MiB input for every block until
|
||||
end of input.
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
If one specifies a size that exceeds the encoder's block size
|
||||
(either the default value in threaded mode or
|
||||
the value specified with \fB\-\-block\-size=\fIsize\fR),
|
||||
@@ -1018,7 +1014,7 @@ For example, if one specifies
|
||||
and the input file is 80 MiB,
|
||||
one will get 11 blocks:
|
||||
5, 10, 8, 10, 2, 10, 10, 4, 10, 10, and 1 MiB.
|
||||
.IP ""
|
||||
.IP
|
||||
In multi-threaded mode the sizes of the blocks
|
||||
are stored in the block headers.
|
||||
This isn't done in single-threaded mode,
|
||||
@@ -1041,7 +1037,7 @@ values make the data available at the receiving end
|
||||
with a small delay, but large
|
||||
.I timeout
|
||||
values give better compression ratio.
|
||||
.IP ""
|
||||
.IP
|
||||
This feature is disabled by default.
|
||||
If this option is specified more than once, the last one takes effect.
|
||||
The special
|
||||
@@ -1049,9 +1045,9 @@ The special
|
||||
value of
|
||||
.B 0
|
||||
can be used to explicitly disable this feature.
|
||||
.IP ""
|
||||
.IP
|
||||
This feature is not available on non-POSIX systems.
|
||||
.IP ""
|
||||
.IP
|
||||
.\" FIXME
|
||||
.B "This feature is still experimental."
|
||||
Currently
|
||||
@@ -1070,12 +1066,12 @@ it is possible that the target file was not written
|
||||
to the storage device but the delete operation was.
|
||||
In that case neither the original source file
|
||||
nor the target file is available.
|
||||
.IP ""
|
||||
.IP
|
||||
This option has an effect only when
|
||||
.B xz
|
||||
is going to remove the source file.
|
||||
In other cases synchronization is never done.
|
||||
.IP ""
|
||||
.IP
|
||||
The synchronization and
|
||||
.B \-\-no\-sync
|
||||
were added in
|
||||
@@ -1086,7 +1082,7 @@ were added in
|
||||
Set a memory usage limit for compression.
|
||||
If this option is specified multiple times,
|
||||
the last one takes effect.
|
||||
.IP ""
|
||||
.IP
|
||||
If the compression settings exceed the
|
||||
.IR limit ,
|
||||
.B xz
|
||||
@@ -1099,7 +1095,7 @@ switching to single-threaded mode
|
||||
if even one thread in multi-threaded mode exceeds the
|
||||
.IR limit ,
|
||||
and finally reducing the LZMA2 dictionary size.
|
||||
.IP ""
|
||||
.IP
|
||||
When compressing with
|
||||
.B \-\-format=raw
|
||||
or if
|
||||
@@ -1107,14 +1103,14 @@ or if
|
||||
has been specified,
|
||||
only the number of threads may be reduced
|
||||
since it can be done without affecting the compressed output.
|
||||
.IP ""
|
||||
.IP
|
||||
If the
|
||||
.I limit
|
||||
cannot be met even with the adjustments described above,
|
||||
an error is displayed and
|
||||
.B xz
|
||||
will exit with exit status 1.
|
||||
.IP ""
|
||||
.IP
|
||||
The
|
||||
.I limit
|
||||
can be specified in multiple ways:
|
||||
@@ -1151,7 +1147,7 @@ to
|
||||
.B max
|
||||
(no memory usage limit).
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
For 32-bit
|
||||
.B xz
|
||||
there is a special case: if the
|
||||
@@ -1174,7 +1170,7 @@ A similar feature doesn't exist for decompression.)
|
||||
This can be helpful when a 32-bit executable has access
|
||||
to 4\ GiB address space (2 GiB on MIPS32)
|
||||
while hopefully doing no harm in other situations.
|
||||
.IP ""
|
||||
.IP
|
||||
See also the section
|
||||
.BR "Memory usage" .
|
||||
.TP
|
||||
@@ -1213,14 +1209,14 @@ and so the effective
|
||||
.I limit
|
||||
for multi-threading will never be higher than the limit set with
|
||||
.BR \-\-memlimit\-decompress .
|
||||
.IP ""
|
||||
.IP
|
||||
In contrast to the other memory usage limit options,
|
||||
.BI \-\-memlimit\-mt\-decompress= limit
|
||||
has a system-specific default
|
||||
.IR limit .
|
||||
.B "xz \-\-info\-memory"
|
||||
can be used to see the current value.
|
||||
.IP ""
|
||||
.IP
|
||||
This option and its default value exist
|
||||
because without any limit the threaded decompressor
|
||||
could end up allocating an insane amount of memory with some input files.
|
||||
@@ -1236,7 +1232,7 @@ will attempt to use that amount of memory
|
||||
even with a low number of threads.
|
||||
Running out of memory or swapping
|
||||
will not improve decompression performance.
|
||||
.IP ""
|
||||
.IP
|
||||
See
|
||||
.BI \-\-memlimit\-compress= limit
|
||||
for possible ways to specify the
|
||||
@@ -1264,7 +1260,7 @@ from switching the encoder from multi-threaded mode to single-threaded mode
|
||||
and from reducing the LZMA2 dictionary size.
|
||||
Even when this option is used the number of threads may be reduced
|
||||
to meet the memory usage limit as that won't affect the compressed output.
|
||||
.IP ""
|
||||
.IP
|
||||
Automatic adjusting is always disabled when creating raw streams
|
||||
.RB ( \-\-format=raw ).
|
||||
.TP
|
||||
@@ -1282,7 +1278,7 @@ The actual number of threads can be fewer than
|
||||
if the input file is not big enough
|
||||
for threading with the given settings or
|
||||
if using more threads would exceed the memory usage limit.
|
||||
.IP ""
|
||||
.IP
|
||||
The single-threaded and multi-threaded compressors produce different output.
|
||||
Single-threaded compressor will give the smallest file size but
|
||||
only the output from the multi-threaded compressor can be decompressed
|
||||
@@ -1301,7 +1297,7 @@ even if the system supports only one hardware thread.
|
||||
.RB ( xz
|
||||
5.2.x
|
||||
used single-threaded mode in this situation.)
|
||||
.IP ""
|
||||
.IP
|
||||
To use multi-threaded mode with only one thread, set
|
||||
.I threads
|
||||
to
|
||||
@@ -1320,7 +1316,7 @@ Support for the
|
||||
prefix was added in
|
||||
.B xz
|
||||
5.4.0.
|
||||
.IP ""
|
||||
.IP
|
||||
If an automatic number of threads has been requested and
|
||||
no memory usage limit has been specified,
|
||||
then a system-specific default soft limit will be used to possibly
|
||||
@@ -1335,14 +1331,14 @@ This default soft limit will not make
|
||||
switch from multi-threaded mode to single-threaded mode.
|
||||
The active limits can be seen with
|
||||
.BR "xz \-\-info\-memory" .
|
||||
.IP ""
|
||||
.IP
|
||||
Currently the only threading method is to split the input into
|
||||
blocks and compress them independently from each other.
|
||||
The default block size depends on the compression level and
|
||||
can be overridden with the
|
||||
.BI \-\-block\-size= size
|
||||
option.
|
||||
.IP ""
|
||||
.IP
|
||||
Threaded decompression only works on files that contain
|
||||
multiple blocks with size information in block headers.
|
||||
All large enough files compressed in multi-threaded mode
|
||||
@@ -1350,7 +1346,7 @@ meet this condition,
|
||||
but files compressed in single-threaded mode don't even if
|
||||
.BI \-\-block\-size= size
|
||||
has been used.
|
||||
.IP ""
|
||||
.IP
|
||||
The default value for
|
||||
.I threads
|
||||
is
|
||||
@@ -1457,7 +1453,7 @@ to apply the same options as
|
||||
\fB\-\-filters1\fR=\fIfilters\fR ... \fB\-\-filters9\fR=\fIfilters
|
||||
Specify up to nine additional filter chains that can be used with
|
||||
.BR \-\-block\-list .
|
||||
.IP ""
|
||||
.IP
|
||||
For example, when compressing an archive with executable files
|
||||
followed by text files, the executable part could use a filter
|
||||
chain with a BCJ filter and the text part only the LZMA2 filter.
|
||||
@@ -1479,7 +1475,7 @@ options, and exit successfully.
|
||||
.PD
|
||||
Add LZMA1 or LZMA2 filter to the filter chain.
|
||||
These filters can be used only as the last filter in the chain.
|
||||
.IP ""
|
||||
.IP
|
||||
LZMA1 is a legacy filter,
|
||||
which is supported almost solely due to the legacy
|
||||
.B .lzma
|
||||
@@ -1491,7 +1487,7 @@ The
|
||||
format uses LZMA2 and doesn't support LZMA1 at all.
|
||||
Compression speed and ratios of LZMA1 and LZMA2
|
||||
are practically the same.
|
||||
.IP ""
|
||||
.IP
|
||||
LZMA1 and LZMA2 share the same set of
|
||||
.IR options :
|
||||
.RS
|
||||
@@ -1542,7 +1538,7 @@ Thus, increasing dictionary
|
||||
.I size
|
||||
usually improves compression ratio, but
|
||||
a dictionary bigger than the uncompressed file is waste of memory.
|
||||
.IP ""
|
||||
.IP
|
||||
Typical dictionary
|
||||
.I size
|
||||
is from 64\ KiB to 64\ MiB.
|
||||
@@ -1551,7 +1547,7 @@ The maximum for compression is currently 1.5\ GiB (1536\ MiB).
|
||||
The decompressor already supports dictionaries up to
|
||||
one byte less than 4\ GiB, which is the maximum for
|
||||
the LZMA1 and LZMA2 stream formats.
|
||||
.IP ""
|
||||
.IP
|
||||
Dictionary
|
||||
.I size
|
||||
and match finder
|
||||
@@ -1587,12 +1583,12 @@ In addition, the sum of
|
||||
and
|
||||
.I lp
|
||||
must not exceed 4.
|
||||
.IP ""
|
||||
.IP
|
||||
All bytes that cannot be encoded as matches
|
||||
are encoded as literals.
|
||||
That is, literals are simply 8-bit bytes
|
||||
that are encoded one at a time.
|
||||
.IP ""
|
||||
.IP
|
||||
The literal coding makes an assumption that the highest
|
||||
.I lc
|
||||
bits of the previous uncompressed byte correlate
|
||||
@@ -1606,7 +1602,7 @@ When
|
||||
.I lc
|
||||
is at least 3, the literal coding can take advantage of
|
||||
this property in the uncompressed data.
|
||||
.IP ""
|
||||
.IP
|
||||
The default value (3) is usually good.
|
||||
If you want maximum compression, test
|
||||
.BR lc=4 .
|
||||
@@ -1619,7 +1615,7 @@ too.
|
||||
.BI lp= lp
|
||||
Specify the number of literal position bits.
|
||||
The minimum is 0 and the maximum is 4; the default is 0.
|
||||
.IP ""
|
||||
.IP
|
||||
.I Lp
|
||||
affects what kind of alignment in the uncompressed data is
|
||||
assumed when encoding literals.
|
||||
@@ -1630,14 +1626,14 @@ below for more information about alignment.
|
||||
.BI pb= pb
|
||||
Specify the number of position bits.
|
||||
The minimum is 0 and the maximum is 4; the default is 2.
|
||||
.IP ""
|
||||
.IP
|
||||
.I Pb
|
||||
affects what kind of alignment in the uncompressed data is
|
||||
assumed in general.
|
||||
The default means four-byte alignment
|
||||
.RI (2^ pb =2^2=4),
|
||||
which is often a good choice when there's no better guess.
|
||||
.IP ""
|
||||
.IP
|
||||
When the alignment is known, setting
|
||||
.I pb
|
||||
accordingly may reduce the file size a little.
|
||||
@@ -1651,7 +1647,7 @@ is a good choice.
|
||||
If the alignment is an odd number like 3 bytes,
|
||||
.B pb=0
|
||||
might be the best choice.
|
||||
.IP ""
|
||||
.IP
|
||||
Even though the assumed alignment can be adjusted with
|
||||
.I pb
|
||||
and
|
||||
@@ -1674,7 +1670,7 @@ use
|
||||
.BR hc4 ,
|
||||
and the rest use
|
||||
.BR bt4 .
|
||||
.IP ""
|
||||
.IP
|
||||
The following match finders are supported.
|
||||
The memory usage formulas below are rough approximations,
|
||||
which are closest to the reality when
|
||||
@@ -1790,7 +1786,7 @@ for
|
||||
for
|
||||
.I presets
|
||||
4\(en9.
|
||||
.IP ""
|
||||
.IP
|
||||
Usually
|
||||
.B fast
|
||||
is used with Hash Chain match finders and
|
||||
@@ -1806,7 +1802,7 @@ Once a match of at least
|
||||
.I nice
|
||||
bytes is found, the algorithm stops
|
||||
looking for possibly better matches.
|
||||
.IP ""
|
||||
.IP
|
||||
.I Nice
|
||||
can be 2\(en273 bytes.
|
||||
Higher values tend to give better compression ratio
|
||||
@@ -1823,7 +1819,7 @@ from
|
||||
.I mf
|
||||
and
|
||||
.IR nice .
|
||||
.IP ""
|
||||
.IP
|
||||
Reasonable
|
||||
.I depth
|
||||
for Hash Chains is 4\(en100 and 16\(en1000 for Binary Trees.
|
||||
@@ -1835,7 +1831,7 @@ Avoid setting the
|
||||
over 1000 unless you are prepared to interrupt
|
||||
the compression in case it is taking far too long.
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
When decoding raw streams
|
||||
.RB ( \-\-format=raw ),
|
||||
LZMA2 needs only the dictionary
|
||||
@@ -1866,7 +1862,7 @@ and
|
||||
Add a branch/call/jump (BCJ) filter to the filter chain.
|
||||
These filters can be used only as a non-last filter
|
||||
in the filter chain.
|
||||
.IP ""
|
||||
.IP
|
||||
A BCJ filter converts relative addresses in
|
||||
the machine code to their absolute counterparts.
|
||||
This doesn't change the size of the data
|
||||
@@ -1880,7 +1876,7 @@ doesn't cause any data loss, although it may make
|
||||
the compression ratio slightly worse.
|
||||
The BCJ filters are very fast and
|
||||
use an insignificant amount of memory.
|
||||
.IP ""
|
||||
.IP
|
||||
These BCJ filters have known problems related to
|
||||
the compression ratio:
|
||||
.RS
|
||||
@@ -1901,12 +1897,11 @@ The contents of non-executable files in the same archive can matter too.
|
||||
In practice one has to try with and without a BCJ filter to see
|
||||
which is better in each situation.
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
Different instruction sets have different alignment:
|
||||
the executable file must be aligned to a multiple of
|
||||
this value in the input data to make the filter work.
|
||||
.RS
|
||||
.RS
|
||||
.PP
|
||||
.TS
|
||||
tab(;);
|
||||
@@ -1923,8 +1918,7 @@ SPARC;4;
|
||||
RISC-V;2;
|
||||
.TE
|
||||
.RE
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
Since the BCJ-filtered data is usually compressed with LZMA2,
|
||||
the compression ratio may be improved slightly if
|
||||
the LZMA2 options are set to match the
|
||||
@@ -1961,7 +1955,7 @@ It's usually good to stick to LZMA2's defaults
|
||||
.RB ( pb=2,lp=0,lc=3 )
|
||||
when compressing x86 executables.
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
All BCJ filters support the same
|
||||
.IR options :
|
||||
.RS
|
||||
@@ -1985,7 +1979,7 @@ is almost never useful.
|
||||
Add the Delta filter to the filter chain.
|
||||
The Delta filter can be only used as a non-last filter
|
||||
in the filter chain.
|
||||
.IP ""
|
||||
.IP
|
||||
Currently only simple byte-wise delta calculation is supported.
|
||||
It can be useful when compressing, for example, uncompressed bitmap images
|
||||
or uncompressed PCM audio.
|
||||
@@ -1994,7 +1988,7 @@ results than Delta + LZMA2.
|
||||
This is true especially with audio,
|
||||
which compresses faster and better, for example, with
|
||||
.BR flac (1).
|
||||
.IP ""
|
||||
.IP
|
||||
Supported
|
||||
.IR options :
|
||||
.RS
|
||||
@@ -2006,7 +2000,7 @@ of the delta calculation in bytes.
|
||||
.I distance
|
||||
must be 1\(en256.
|
||||
The default is 1.
|
||||
.IP ""
|
||||
.IP
|
||||
For example, with
|
||||
.B dist=2
|
||||
and eight-byte input A1 B1 A2 B3 A3 B5 A4 B7, the output will be
|
||||
@@ -2030,7 +2024,7 @@ will display a progress indicator.
|
||||
Specifying
|
||||
.B \-\-verbose
|
||||
twice will give even more verbose output.
|
||||
.IP ""
|
||||
.IP
|
||||
The progress indicator shows the following information:
|
||||
.RS
|
||||
.IP \(bu 3
|
||||
@@ -2065,7 +2059,7 @@ started processing the file.
|
||||
The time is shown in a less precise format which
|
||||
never has any colons, for example, 2 min 30 s.
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
When standard error is not a terminal,
|
||||
.B \-\-verbose
|
||||
will make
|
||||
@@ -2641,7 +2635,7 @@ XZ_OPT=\-2v tar caf foo.tar.xz foo
|
||||
.fi
|
||||
.RE
|
||||
.RE
|
||||
.IP ""
|
||||
.IP
|
||||
Scripts may use
|
||||
.BR XZ_OPT ,
|
||||
for example, to set script-specific default compression options.
|
||||
|
||||
Reference in new issue
Block a user