diff options
-rw-r--r-- | archival/gzip.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/archival/gzip.c b/archival/gzip.c index efc5a0eea..4a3fe976a 100644 --- a/archival/gzip.c +++ b/archival/gzip.c | |||
@@ -355,7 +355,7 @@ struct globals { | |||
355 | /* Output buffer. bits are inserted starting at the bottom (least significant | 355 | /* Output buffer. bits are inserted starting at the bottom (least significant |
356 | * bits). | 356 | * bits). |
357 | */ | 357 | */ |
358 | unsigned short bi_buf; | 358 | unsigned bi_buf; /* was unsigned short */ |
359 | 359 | ||
360 | #undef BUF_SIZE | 360 | #undef BUF_SIZE |
361 | #define BUF_SIZE (int)(8 * sizeof(G1.bi_buf)) | 361 | #define BUF_SIZE (int)(8 * sizeof(G1.bi_buf)) |
@@ -530,17 +530,25 @@ static void send_bits(int value, int length) | |||
530 | Assert(length > 0 && length <= 15, "invalid length"); | 530 | Assert(length > 0 && length <= 15, "invalid length"); |
531 | G1.bits_sent += length; | 531 | G1.bits_sent += length; |
532 | #endif | 532 | #endif |
533 | BUILD_BUG_ON(BUF_SIZE != 32 && BUF_SIZE != 16); | ||
533 | 534 | ||
534 | new_buf = G1.bi_buf | (value << G1.bi_valid); | 535 | new_buf = G1.bi_buf | (value << G1.bi_valid); |
536 | /* NB: the above may sometimes do "<< 32" shift (undefined) | ||
537 | * if check below is changed to "length > remain" instead of >= */ | ||
535 | remain = BUF_SIZE - G1.bi_valid; | 538 | remain = BUF_SIZE - G1.bi_valid; |
536 | /* If not enough room in bi_buf */ | 539 | |
537 | if (length > remain) { | 540 | /* If bi_buf is full */ |
541 | if (length >= remain) { | ||
538 | /* ...use (valid) bits from bi_buf and | 542 | /* ...use (valid) bits from bi_buf and |
539 | * (16 - bi_valid) bits from value, | 543 | * (BUF_SIZE - bi_valid) bits from value, |
540 | * leaving (width - (16-bi_valid)) unused bits in value. | 544 | * leaving (width - (BUF_SIZE-bi_valid)) unused bits in value. |
541 | */ | 545 | */ |
542 | put_16bit(new_buf); | 546 | if (BUF_SIZE == 32) { |
543 | new_buf = (ush) value >> remain; | 547 | put_32bit(new_buf); /* maybe unroll to 2*put_16bit()? */ |
548 | } else { /* 16 */ | ||
549 | put_16bit(new_buf); | ||
550 | } | ||
551 | new_buf = (unsigned) value >> remain; | ||
544 | length -= BUF_SIZE; | 552 | length -= BUF_SIZE; |
545 | } | 553 | } |
546 | G1.bi_buf = new_buf; | 554 | G1.bi_buf = new_buf; |
@@ -571,10 +579,13 @@ static unsigned bi_reverse(unsigned code, int len) | |||
571 | */ | 579 | */ |
572 | static void bi_windup(void) | 580 | static void bi_windup(void) |
573 | { | 581 | { |
574 | if (G1.bi_valid > 8) { | 582 | unsigned bits = G1.bi_buf; |
575 | put_16bit(G1.bi_buf); | 583 | int cnt = G1.bi_valid; |
576 | } else if (G1.bi_valid > 0) { | 584 | |
577 | put_8bit(G1.bi_buf); | 585 | while (cnt > 0) { |
586 | put_8bit(bits); | ||
587 | bits >>= 8; | ||
588 | cnt -= 8; | ||
578 | } | 589 | } |
579 | G1.bi_buf = 0; | 590 | G1.bi_buf = 0; |
580 | G1.bi_valid = 0; | 591 | G1.bi_valid = 0; |