diff options
Diffstat (limited to 'lib/decompress_unlzma.c')
-rw-r--r-- | lib/decompress_unlzma.c | 85 |
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 | ||
85 | static int nofill(void *buffer, unsigned int len) | 85 | static 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() */ | ||
131 | static 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() */ |
137 | static void INIT rc_do_normalize(struct rc *rc) | 131 | static 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 | } |
172 | static inline void rc_update_bit_1(struct rc *rc, uint16_t *p) | 166 | static 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 | ||
322 | static inline void INIT write_byte(struct writer *wr, uint8_t byte) | 316 | static 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 | ||
333 | static inline void INIT copy_byte(struct writer *wr, uint32_t offs) | 330 | static 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 | ||
338 | static inline void INIT copy_bytes(struct writer *wr, | 335 | static 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 | ||
347 | static inline void INIT process_bit0(struct writer *wr, struct rc *rc, | 347 | static 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 | ||
390 | static inline void INIT process_bit1(struct writer *wr, struct rc *rc, | 391 | static 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; | 657 | exit_3: |
645 | large_free(p); | 658 | large_free(p); |
646 | exit_2: | 659 | exit_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 |