diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-05 17:04:47 +0300 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-05 17:04:47 +0300 |
commit | 3376298b59abea4ec3c69fe1dbe5898db260cc5a (patch) | |
tree | a831c13cfb8e839ddf5d020a879d3e4d8c0376f8 /archival/libunarchive/decompress_unlzma.c | |
parent | 98b8e9487dc40100d8031136f2241a66ce9dffb0 (diff) |
Stop tracking buffer size - it is a constant.
Stop ignoring write errors.
Fix bugs in this line:
rc->buffer_size = read(rc->fd, RC_BUFFER, rc->buffer_size);
(a) should use safe_read()
(b) just ONE short read (e.g. 4 bytes) will make ALL future reads short!
Diffstat (limited to 'archival/libunarchive/decompress_unlzma.c')
-rw-r--r-- | archival/libunarchive/decompress_unlzma.c | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/archival/libunarchive/decompress_unlzma.c b/archival/libunarchive/decompress_unlzma.c index c1b0a3118..15a0275b4 100644 --- a/archival/libunarchive/decompress_unlzma.c +++ b/archival/libunarchive/decompress_unlzma.c @@ -22,17 +22,23 @@ typedef struct { int fd; uint8_t *ptr; -// uint8_t *buffer; + +/* Was keeping rc on stack in unlzma and separately allocating buffer, + * but with "buffer 'attached to' allocated rc" code is smaller: */ + /* uint8_t *buffer; */ +#define RC_BUFFER ((uint8_t*)(rc+1)) + uint8_t *buffer_end; - int buffer_size; + +/* Had provisions for variable buffer, but we don't need it here */ + /* int buffer_size; */ +#define RC_BUFFER_SIZE 0x10000 + uint32_t code; uint32_t range; uint32_t bound; } rc_t; -//#define RC_BUFFER ((uint8_t*)(void*)(rc+1)) -#define RC_BUFFER ((uint8_t*)(rc+1)) - #define RC_TOP_BITS 24 #define RC_MOVE_BITS 5 #define RC_MODEL_TOTAL_BITS 11 @@ -41,24 +47,24 @@ typedef struct { /* Called twice: once at startup and once in rc_normalize() */ static void rc_read(rc_t * rc) { - rc->buffer_size = read(rc->fd, RC_BUFFER, rc->buffer_size); - if (rc->buffer_size <= 0) + int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE); + if (buffer_size <= 0) bb_error_msg_and_die("unexpected EOF"); rc->ptr = RC_BUFFER; - rc->buffer_end = RC_BUFFER + rc->buffer_size; + rc->buffer_end = RC_BUFFER + buffer_size; } /* Called once */ -static rc_t* rc_init(int fd, int buffer_size) +static rc_t* rc_init(int fd) /*, int buffer_size) */ { int i; rc_t* rc; - rc = xmalloc(sizeof(rc_t) + buffer_size); + rc = xmalloc(sizeof(rc_t) + RC_BUFFER_SIZE); rc->fd = fd; - rc->buffer_size = buffer_size; - rc->buffer_end = RC_BUFFER + rc->buffer_size; + /* rc->buffer_size = buffer_size; */ + rc->buffer_end = RC_BUFFER + RC_BUFFER_SIZE; rc->ptr = rc->buffer_end; rc->code = 0; @@ -168,7 +174,7 @@ typedef struct { } __attribute__ ((packed)) lzma_header_t; -/* #defines will make compiler to compute/optimize each one with each usage. +/* #defines will force compiler to compute/optimize each one with each usage. * Have heart and use enum instead. */ enum { LZMA_BASE_SIZE = 1846, @@ -244,8 +250,7 @@ unlzma(int src_fd, int dst_fd) int state = 0; uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; - if (read(src_fd, &header, sizeof(header)) != sizeof(header)) - bb_error_msg_and_die("can't read header"); + xread(src_fd, &header, sizeof(header)); if (header.pos >= (9 * 5 * 5)) bb_error_msg_and_die("bad header"); @@ -270,7 +275,7 @@ unlzma(int src_fd, int dst_fd) for (i = 0; i < num_probs; i++) p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; - rc = rc_init(src_fd, 0x10000); + rc = rc_init(src_fd); /*, RC_BUFFER_SIZE); */ while (global_pos + buffer_pos < header.dst_size) { int pos_state = (buffer_pos + global_pos) & pos_state_mask; @@ -316,8 +321,8 @@ unlzma(int src_fd, int dst_fd) if (buffer_pos == header.dict_size) { buffer_pos = 0; global_pos += header.dict_size; - // FIXME: error check - write(dst_fd, buffer, header.dict_size); + if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size) + goto bad; USE_DESKTOP(total_written += header.dict_size;) } if (state < 4) @@ -358,8 +363,8 @@ unlzma(int src_fd, int dst_fd) if (buffer_pos == header.dict_size) { buffer_pos = 0; global_pos += header.dict_size; - // FIXME: error check - write(dst_fd, buffer, header.dict_size); + if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size) + goto bad; USE_DESKTOP(total_written += header.dict_size;) } continue; @@ -471,8 +476,8 @@ unlzma(int src_fd, int dst_fd) if (buffer_pos == header.dict_size) { buffer_pos = 0; global_pos += header.dict_size; - // FIXME: error check - write(dst_fd, buffer, header.dict_size); + if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size) + goto bad; USE_DESKTOP(total_written += header.dict_size;) } len--; @@ -480,9 +485,13 @@ unlzma(int src_fd, int dst_fd) } } - // FIXME: error check - write(dst_fd, buffer, buffer_pos); - USE_DESKTOP(total_written += buffer_pos;) + + if (full_write(dst_fd, buffer, buffer_pos) != buffer_pos) { + bad: + rc_free(rc); + return -1; + } rc_free(rc); + USE_DESKTOP(total_written += buffer_pos;) return USE_DESKTOP(total_written) + 0; } |