blob: da6dfa80233c0051e4defc52e2ead5c9c290249e [file] [log] [blame]
busybox-1.27.2: Fix lzma segfaults
[No upstream tracking] -- https://bugs.busybox.net/show_bug.cgi?id=10871
libarchive: check buffer index in lzma_decompress
With specific defconfig busybox fails to check zip fileheader magic
(archival/unzip.c) and uses (archival/libarchive/decompress_unlzma.c)
for decompression which leads to segmentation fault. It prevents accessing into
buffer, which is smaller than pos index. Patch includes multiple segmentation
fault fixes.
Upstream-Status: Backport [https://git.busybox.net/busybox/commit/?id=a36986bb80289c1cd8d15a557e49207c9a42946b]
bug: 10436 10871
Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c
index a904087..29eee2a 100644
--- a/archival/libarchive/decompress_unlzma.c
+++ b/archival/libarchive/decompress_unlzma.c
@@ -11,6 +11,14 @@
#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
@@ -217,6 +225,7 @@ 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;
int len = 0;
@@ -246,7 +255,8 @@ unpack_lzma_stream(transformer_state_t *xstate)
if (header.dict_size == 0)
header.dict_size++;
- buffer = xmalloc(MIN(header.dst_size, header.dict_size));
+ buffer_size = MIN(header.dst_size, header.dict_size);
+ buffer = xmalloc(buffer_size);
{
int num_probs;
@@ -341,8 +351,12 @@ unpack_lzma_stream(transformer_state_t *xstate)
state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
pos = buffer_pos - rep0;
- if ((int32_t)pos < 0)
+ if ((int32_t)pos < 0) {
pos += header.dict_size;
+ /* see unzip_bad_lzma_2.zip: */
+ if (pos >= buffer_size)
+ goto bad;
+ }
previous_byte = buffer[pos];
goto one_byte1;
#else
@@ -417,6 +431,10 @@ 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;
+ if ((int32_t)rep0 < 0) {
+ dbg("%d rep0:%d", __LINE__, rep0);
+ goto bad;
+ }
prob3 = p + LZMA_ALIGN;
}
i2 = 1;
@@ -450,8 +468,12 @@ unpack_lzma_stream(transformer_state_t *xstate)
IF_NOT_FEATURE_LZMA_FAST(string:)
do {
uint32_t pos = buffer_pos - rep0;
- if ((int32_t)pos < 0)
+ if ((int32_t)pos < 0) {
pos += header.dict_size;
+ /* 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;
@@ -478,6 +500,12 @@ unpack_lzma_stream(transformer_state_t *xstate)
IF_DESKTOP(total_written += buffer_pos;)
if (transformer_write(xstate, buffer, buffer_pos) != (ssize_t)buffer_pos) {
bad:
+ /* One of our users, bbunpack(), expects _us_ to emit
+ * the error message (since it's the best place to give
+ * potentially more detailed information).
+ * Do not fail silently.
+ */
+ bb_error_msg("corrupted data");
total_written = -1; /* failure */
}
rc_free(rc);