Changeset a35b458 in mainline for uspace/lib/compress/inflate.c
- Timestamp:
- 2018-03-02T20:10:49Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1380b7
- Parents:
- 3061bc1
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/compress/inflate.c
r3061bc1 ra35b458 103 103 size_t destlen; /**< Output buffer size */ 104 104 size_t destcnt; /**< Position in the output buffer */ 105 105 106 106 uint8_t *src; /**< Input buffer */ 107 107 size_t srclen; /**< Input buffer size */ 108 108 size_t srccnt; /**< Position in the input buffer */ 109 109 110 110 uint16_t bitbuf; /**< Bit buffer */ 111 111 size_t bitlen; /**< Number of bits in the bit buffer */ 112 112 113 113 bool overrun; /**< Overrun condition */ 114 114 } inflate_state_t; … … 240 240 /* Bit accumulator for at least 20 bits */ 241 241 uint32_t val = state->bitbuf; 242 242 243 243 while (state->bitlen < cnt) { 244 244 if (state->srccnt == state->srclen) { … … 246 246 return 0; 247 247 } 248 248 249 249 /* Load 8 more bits */ 250 250 val |= ((uint32_t) state->src[state->srccnt]) << state->bitlen; … … 252 252 state->bitlen += 8; 253 253 } 254 254 255 255 /* Update bits in the buffer */ 256 256 state->bitbuf = (uint16_t) (val >> cnt); 257 257 state->bitlen -= cnt; 258 258 259 259 return ((uint16_t) (val & ((1 << cnt) - 1))); 260 260 } … … 275 275 state->bitbuf = 0; 276 276 state->bitlen = 0; 277 277 278 278 if (state->srccnt + 4 > state->srclen) 279 279 return ELIMIT; 280 280 281 281 uint16_t len = 282 282 state->src[state->srccnt] | (state->src[state->srccnt + 1] << 8); 283 283 uint16_t len_compl = 284 284 state->src[state->srccnt + 2] | (state->src[state->srccnt + 3] << 8); 285 285 286 286 /* Check block length and its complement */ 287 287 if (((int16_t) len) != ~((int16_t) len_compl)) 288 288 return EINVAL; 289 289 290 290 state->srccnt += 4; 291 291 292 292 /* Check input buffer size */ 293 293 if (state->srccnt + len > state->srclen) 294 294 return ELIMIT; 295 295 296 296 /* Check output buffer size */ 297 297 if (state->destcnt + len > state->destlen) 298 298 return ENOMEM; 299 299 300 300 /* Copy data */ 301 301 memcpy(state->dest + state->destcnt, state->src + state->srccnt, len); 302 302 state->srccnt += len; 303 303 state->destcnt += len; 304 304 305 305 return EOK; 306 306 } … … 323 323 size_t index = 0; /* Index of the first code of the given length 324 324 in the symbol table */ 325 325 326 326 size_t len; /* Current number of bits in the code */ 327 327 for (len = 1; len <= MAX_HUFFMAN_BIT; len++) { … … 329 329 code |= get_bits(state, 1); 330 330 CHECK_OVERRUN(*state); 331 331 332 332 uint16_t count = huffman->count[len]; 333 333 if (code < first + count) { … … 336 336 return EOK; 337 337 } 338 338 339 339 /* Update for next length */ 340 340 index += count; … … 343 343 code <<= 1; 344 344 } 345 345 346 346 return EINVAL; 347 347 } … … 364 364 for (len = 0; len <= MAX_HUFFMAN_BIT; len++) 365 365 huffman->count[len] = 0; 366 366 367 367 /* We assume that the lengths are within bounds */ 368 368 size_t symbol; 369 369 for (symbol = 0; symbol < n; symbol++) 370 370 huffman->count[length[symbol]]++; 371 371 372 372 if (huffman->count[0] == n) { 373 373 /* The code is complete, but decoding will fail */ 374 374 return 0; 375 375 } 376 376 377 377 /* Check for an over-subscribed or incomplete set of lengths */ 378 378 int16_t left = 1; … … 385 385 } 386 386 } 387 387 388 388 /* Generate offsets into symbol table */ 389 389 uint16_t offs[MAX_HUFFMAN_BIT + 1]; 390 390 391 391 offs[1] = 0; 392 392 for (len = 1; len < MAX_HUFFMAN_BIT; len++) 393 393 offs[len + 1] = offs[len] + huffman->count[len]; 394 394 395 395 for (symbol = 0; symbol < n; symbol++) { 396 396 if (length[symbol] != 0) { … … 399 399 } 400 400 } 401 401 402 402 return left; 403 403 } … … 422 422 { 423 423 uint16_t symbol; 424 424 425 425 do { 426 426 errno_t err = huffman_decode(state, len_code, &symbol); … … 429 429 return err; 430 430 } 431 431 432 432 if (symbol < 256) { 433 433 /* Write out literal */ 434 434 if (state->destcnt == state->destlen) 435 435 return ENOMEM; 436 436 437 437 state->dest[state->destcnt] = (uint8_t) symbol; 438 438 state->destcnt++; … … 442 442 if (symbol >= 29) 443 443 return EINVAL; 444 444 445 445 size_t len = lens[symbol] + get_bits(state, lens_ext[symbol]); 446 446 CHECK_OVERRUN(*state); 447 447 448 448 /* Get distance */ 449 449 err = huffman_decode(state, dist_code, &symbol); 450 450 if (err != EOK) 451 451 return err; 452 452 453 453 size_t dist = dists[symbol] + get_bits(state, dists_ext[symbol]); 454 454 if (dist > state->destcnt) 455 455 return ENOENT; 456 456 457 457 if (state->destcnt + len > state->destlen) 458 458 return ENOMEM; 459 459 460 460 while (len > 0) { 461 461 /* Copy len bytes from distance bytes back */ … … 467 467 } 468 468 } while (symbol != 256); 469 469 470 470 return EOK; 471 471 } … … 510 510 huffman_t dyn_len_code; 511 511 huffman_t dyn_dist_code; 512 512 513 513 dyn_len_code.count = dyn_len_count; 514 514 dyn_len_code.symbol = dyn_len_symbol; 515 515 516 516 dyn_dist_code.count = dyn_dist_count; 517 517 dyn_dist_code.symbol = dyn_dist_symbol; 518 518 519 519 /* Get number of bits in each table */ 520 520 uint16_t nlen = get_bits(state, 5) + 257; 521 521 CHECK_OVERRUN(*state); 522 522 523 523 uint16_t ndist = get_bits(state, 5) + 1; 524 524 CHECK_OVERRUN(*state); 525 525 526 526 uint16_t ncode = get_bits(state, 4) + 4; 527 527 CHECK_OVERRUN(*state); 528 528 529 529 if ((nlen > MAX_LITLEN) || (ndist > MAX_DIST) 530 530 || (ncode > MAX_ORDER)) 531 531 return EINVAL; 532 532 533 533 /* Read code length code lengths */ 534 534 uint16_t index; … … 537 537 CHECK_OVERRUN(*state); 538 538 } 539 539 540 540 /* Set missing lengths to zero */ 541 541 for (index = ncode; index < MAX_ORDER; index++) 542 542 length[order[index]] = 0; 543 543 544 544 /* Build Huffman code */ 545 545 int16_t rc = huffman_construct(&dyn_len_code, length, MAX_ORDER); 546 546 if (rc != 0) 547 547 return EINVAL; 548 548 549 549 /* Read length/literal and distance code length tables */ 550 550 index = 0; … … 554 554 if (err != EOK) 555 555 return EOK; 556 556 557 557 if (symbol < 16) { 558 558 length[index] = symbol; … … 560 560 } else { 561 561 uint16_t len = 0; 562 562 563 563 if (symbol == 16) { 564 564 if (index == 0) 565 565 return EINVAL; 566 566 567 567 len = length[index - 1]; 568 568 symbol = get_bits(state, 2) + 3; … … 575 575 CHECK_OVERRUN(*state); 576 576 } 577 577 578 578 if (index + symbol > nlen + ndist) 579 579 return EINVAL; 580 580 581 581 while (symbol > 0) { 582 582 length[index] = len; … … 586 586 } 587 587 } 588 588 589 589 /* Check for end-of-block code */ 590 590 if (length[256] == 0) 591 591 return EINVAL; 592 592 593 593 /* Build Huffman tables for literal/length codes */ 594 594 rc = huffman_construct(&dyn_len_code, length, nlen); 595 595 if ((rc < 0) || ((rc > 0) && (dyn_len_code.count[0] + 1 != nlen))) 596 596 return EINVAL; 597 597 598 598 /* Build Huffman tables for distance codes */ 599 599 rc = huffman_construct(&dyn_dist_code, length + nlen, ndist); 600 600 if ((rc < 0) || ((rc > 0) && (dyn_dist_code.count[0] + 1 != ndist))) 601 601 return EINVAL; 602 602 603 603 return inflate_codes(state, &dyn_len_code, &dyn_dist_code); 604 604 } … … 622 622 /* Initialize the state */ 623 623 inflate_state_t state; 624 624 625 625 state.dest = (uint8_t *) dest; 626 626 state.destlen = destlen; 627 627 state.destcnt = 0; 628 628 629 629 state.src = (uint8_t *) src; 630 630 state.srclen = srclen; 631 631 state.srccnt = 0; 632 632 633 633 state.bitbuf = 0; 634 634 state.bitlen = 0; 635 635 636 636 state.overrun = false; 637 637 638 638 uint16_t last; 639 639 errno_t ret = EOK; 640 640 641 641 do { 642 642 /* Last block is indicated by a non-zero bit */ 643 643 last = get_bits(&state, 1); 644 644 CHECK_OVERRUN(state); 645 645 646 646 /* Block type */ 647 647 uint16_t type = get_bits(&state, 2); 648 648 CHECK_OVERRUN(state); 649 649 650 650 switch (type) { 651 651 case 0: … … 662 662 } 663 663 } while ((!last) && (ret == 0)); 664 664 665 665 return ret; 666 666 }
Note:
See TracChangeset
for help on using the changeset viewer.