aboutsummaryrefslogtreecommitdiffstats
path: root/lib/decompress_unlzma.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/decompress_unlzma.c')
-rw-r--r--lib/decompress_unlzma.c85
1 files changed, 49 insertions, 36 deletions
diff --git a/lib/decompress_unlzma.c b/lib/decompress_unlzma.c
index ca82fde81c8..476c65af970 100644
--- a/lib/decompress_unlzma.c
+++ b/lib/decompress_unlzma.c
@@ -33,7 +33,6 @@
33#define PREBOOT 33#define PREBOOT
34#else 34#else
35#include <linux/decompress/unlzma.h> 35#include <linux/decompress/unlzma.h>
36#include <linux/slab.h>
37#endif /* STATIC */ 36#endif /* STATIC */
38 37
39#include <linux/decompress/mm.h> 38#include <linux/decompress/mm.h>
@@ -74,6 +73,7 @@ struct rc {
74 uint32_t code; 73 uint32_t code;
75 uint32_t range; 74 uint32_t range;
76 uint32_t bound; 75 uint32_t bound;
76 void (*error)(char *);
77}; 77};
78 78
79 79
@@ -82,7 +82,7 @@ struct rc {
82#define RC_MODEL_TOTAL_BITS 11 82#define RC_MODEL_TOTAL_BITS 11
83 83
84 84
85static int nofill(void *buffer, unsigned int len) 85static int INIT nofill(void *buffer, unsigned int len)
86{ 86{
87 return -1; 87 return -1;
88} 88}
@@ -92,7 +92,7 @@ static void INIT rc_read(struct rc *rc)
92{ 92{
93 rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE); 93 rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE);
94 if (rc->buffer_size <= 0) 94 if (rc->buffer_size <= 0)
95 error("unexpected EOF"); 95 rc->error("unexpected EOF");
96 rc->ptr = rc->buffer; 96 rc->ptr = rc->buffer;
97 rc->buffer_end = rc->buffer + rc->buffer_size; 97 rc->buffer_end = rc->buffer + rc->buffer_size;
98} 98}
@@ -127,12 +127,6 @@ static inline void INIT rc_init_code(struct rc *rc)
127} 127}
128 128
129 129
130/* Called once. TODO: bb_maybe_free() */
131static inline void INIT rc_free(struct rc *rc)
132{
133 free(rc->buffer);
134}
135
136/* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */ 130/* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */
137static void INIT rc_do_normalize(struct rc *rc) 131static void INIT rc_do_normalize(struct rc *rc)
138{ 132{
@@ -169,7 +163,7 @@ static inline void INIT rc_update_bit_0(struct rc *rc, uint16_t *p)
169 rc->range = rc->bound; 163 rc->range = rc->bound;
170 *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; 164 *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
171} 165}
172static inline void rc_update_bit_1(struct rc *rc, uint16_t *p) 166static inline void INIT rc_update_bit_1(struct rc *rc, uint16_t *p)
173{ 167{
174 rc->range -= rc->bound; 168 rc->range -= rc->bound;
175 rc->code -= rc->bound; 169 rc->code -= rc->bound;
@@ -319,32 +313,38 @@ static inline uint8_t INIT peek_old_byte(struct writer *wr,
319 313
320} 314}
321 315
322static inline void INIT write_byte(struct writer *wr, uint8_t byte) 316static inline int INIT write_byte(struct writer *wr, uint8_t byte)
323{ 317{
324 wr->buffer[wr->buffer_pos++] = wr->previous_byte = byte; 318 wr->buffer[wr->buffer_pos++] = wr->previous_byte = byte;
325 if (wr->flush && wr->buffer_pos == wr->header->dict_size) { 319 if (wr->flush && wr->buffer_pos == wr->header->dict_size) {
326 wr->buffer_pos = 0; 320 wr->buffer_pos = 0;
327 wr->global_pos += wr->header->dict_size; 321 wr->global_pos += wr->header->dict_size;
328 wr->flush((char *)wr->buffer, wr->header->dict_size); 322 if (wr->flush((char *)wr->buffer, wr->header->dict_size)
323 != wr->header->dict_size)
324 return -1;
329 } 325 }
326 return 0;
330} 327}
331 328
332 329
333static inline void INIT copy_byte(struct writer *wr, uint32_t offs) 330static inline int INIT copy_byte(struct writer *wr, uint32_t offs)
334{ 331{
335 write_byte(wr, peek_old_byte(wr, offs)); 332 return write_byte(wr, peek_old_byte(wr, offs));
336} 333}
337 334
338static inline void INIT copy_bytes(struct writer *wr, 335static inline int INIT copy_bytes(struct writer *wr,
339 uint32_t rep0, int len) 336 uint32_t rep0, int len)
340{ 337{
341 do { 338 do {
342 copy_byte(wr, rep0); 339 if (copy_byte(wr, rep0))
340 return -1;
343 len--; 341 len--;
344 } while (len != 0 && wr->buffer_pos < wr->header->dst_size); 342 } while (len != 0 && wr->buffer_pos < wr->header->dst_size);
343
344 return len;
345} 345}
346 346
347static inline void INIT process_bit0(struct writer *wr, struct rc *rc, 347static inline int INIT process_bit0(struct writer *wr, struct rc *rc,
348 struct cstate *cst, uint16_t *p, 348 struct cstate *cst, uint16_t *p,
349 int pos_state, uint16_t *prob, 349 int pos_state, uint16_t *prob,
350 int lc, uint32_t literal_pos_mask) { 350 int lc, uint32_t literal_pos_mask) {
@@ -378,16 +378,17 @@ static inline void INIT process_bit0(struct writer *wr, struct rc *rc,
378 uint16_t *prob_lit = prob + mi; 378 uint16_t *prob_lit = prob + mi;
379 rc_get_bit(rc, prob_lit, &mi); 379 rc_get_bit(rc, prob_lit, &mi);
380 } 380 }
381 write_byte(wr, mi);
382 if (cst->state < 4) 381 if (cst->state < 4)
383 cst->state = 0; 382 cst->state = 0;
384 else if (cst->state < 10) 383 else if (cst->state < 10)
385 cst->state -= 3; 384 cst->state -= 3;
386 else 385 else
387 cst->state -= 6; 386 cst->state -= 6;
387
388 return write_byte(wr, mi);
388} 389}
389 390
390static inline void INIT process_bit1(struct writer *wr, struct rc *rc, 391static inline int INIT process_bit1(struct writer *wr, struct rc *rc,
391 struct cstate *cst, uint16_t *p, 392 struct cstate *cst, uint16_t *p,
392 int pos_state, uint16_t *prob) { 393 int pos_state, uint16_t *prob) {
393 int offset; 394 int offset;
@@ -418,8 +419,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
418 419
419 cst->state = cst->state < LZMA_NUM_LIT_STATES ? 420 cst->state = cst->state < LZMA_NUM_LIT_STATES ?
420 9 : 11; 421 9 : 11;
421 copy_byte(wr, cst->rep0); 422 return copy_byte(wr, cst->rep0);
422 return;
423 } else { 423 } else {
424 rc_update_bit_1(rc, prob); 424 rc_update_bit_1(rc, prob);
425 } 425 }
@@ -521,12 +521,15 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
521 } else 521 } else
522 cst->rep0 = pos_slot; 522 cst->rep0 = pos_slot;
523 if (++(cst->rep0) == 0) 523 if (++(cst->rep0) == 0)
524 return; 524 return 0;
525 if (cst->rep0 > wr->header->dict_size
526 || cst->rep0 > get_pos(wr))
527 return -1;
525 } 528 }
526 529
527 len += LZMA_MATCH_MIN_LEN; 530 len += LZMA_MATCH_MIN_LEN;
528 531
529 copy_bytes(wr, cst->rep0, len); 532 return copy_bytes(wr, cst->rep0, len);
530} 533}
531 534
532 535
@@ -536,7 +539,7 @@ STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
536 int(*flush)(void*, unsigned int), 539 int(*flush)(void*, unsigned int),
537 unsigned char *output, 540 unsigned char *output,
538 int *posp, 541 int *posp,
539 void(*error_fn)(char *x) 542 void(*error)(char *x)
540 ) 543 )
541{ 544{
542 struct lzma_header header; 545 struct lzma_header header;
@@ -552,7 +555,7 @@ STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
552 unsigned char *inbuf; 555 unsigned char *inbuf;
553 int ret = -1; 556 int ret = -1;
554 557
555 set_error_fn(error_fn); 558 rc.error = error;
556 559
557 if (buf) 560 if (buf)
558 inbuf = buf; 561 inbuf = buf;
@@ -580,8 +583,10 @@ STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
580 ((unsigned char *)&header)[i] = *rc.ptr++; 583 ((unsigned char *)&header)[i] = *rc.ptr++;
581 } 584 }
582 585
583 if (header.pos >= (9 * 5 * 5)) 586 if (header.pos >= (9 * 5 * 5)) {
584 error("bad header"); 587 error("bad header");
588 goto exit_1;
589 }
585 590
586 mi = 0; 591 mi = 0;
587 lc = header.pos; 592 lc = header.pos;
@@ -627,21 +632,29 @@ STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
627 int pos_state = get_pos(&wr) & pos_state_mask; 632 int pos_state = get_pos(&wr) & pos_state_mask;
628 uint16_t *prob = p + LZMA_IS_MATCH + 633 uint16_t *prob = p + LZMA_IS_MATCH +
629 (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state; 634 (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state;
630 if (rc_is_bit_0(&rc, prob)) 635 if (rc_is_bit_0(&rc, prob)) {
631 process_bit0(&wr, &rc, &cst, p, pos_state, prob, 636 if (process_bit0(&wr, &rc, &cst, p, pos_state, prob,
632 lc, literal_pos_mask); 637 lc, literal_pos_mask)) {
633 else { 638 error("LZMA data is corrupt");
634 process_bit1(&wr, &rc, &cst, p, pos_state, prob); 639 goto exit_3;
640 }
641 } else {
642 if (process_bit1(&wr, &rc, &cst, p, pos_state, prob)) {
643 error("LZMA data is corrupt");
644 goto exit_3;
645 }
635 if (cst.rep0 == 0) 646 if (cst.rep0 == 0)
636 break; 647 break;
637 } 648 }
649 if (rc.buffer_size <= 0)
650 goto exit_3;
638 } 651 }
639 652
640 if (posp) 653 if (posp)
641 *posp = rc.ptr-rc.buffer; 654 *posp = rc.ptr-rc.buffer;
642 if (wr.flush) 655 if (!wr.flush || wr.flush(wr.buffer, wr.buffer_pos) == wr.buffer_pos)
643 wr.flush(wr.buffer, wr.buffer_pos); 656 ret = 0;
644 ret = 0; 657exit_3:
645 large_free(p); 658 large_free(p);
646exit_2: 659exit_2:
647 if (!output) 660 if (!output)
@@ -659,9 +672,9 @@ STATIC int INIT decompress(unsigned char *buf, int in_len,
659 int(*flush)(void*, unsigned int), 672 int(*flush)(void*, unsigned int),
660 unsigned char *output, 673 unsigned char *output,
661 int *posp, 674 int *posp,
662 void(*error_fn)(char *x) 675 void(*error)(char *x)
663 ) 676 )
664{ 677{
665 return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn); 678 return unlzma(buf, in_len - 4, fill, flush, output, posp, error);
666} 679}
667#endif 680#endif