Decompressor.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
  2. // Copyright 2015, SIL International, All rights reserved.
  3. #include <cassert>
  4. #include "inc/Decompressor.h"
  5. #include "inc/Compression.h"
  6. using namespace lz4;
  7. namespace {
  8. inline
  9. u32 read_literal(u8 const * &s, u8 const * const e, u32 l) {
  10. if (l == 15 && s != e)
  11. {
  12. u8 b = 0;
  13. do { l += b = *s++; } while(b==0xff && s != e);
  14. }
  15. return l;
  16. }
  17. bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal,
  18. u32 & literal_len, u32 & match_len, u32 & match_dist)
  19. {
  20. u8 const token = *src++;
  21. literal_len = read_literal(src, end, token >> 4);
  22. literal = src;
  23. src += literal_len;
  24. // Normal exit for end of stream, wrap arround check and parital match check.
  25. if (src > end - sizeof(u16) || src < literal)
  26. return false;
  27. match_dist = *src++;
  28. match_dist |= *src++ << 8;
  29. match_len = read_literal(src, end, token & 0xf) + MINMATCH;
  30. // Malformed stream check.
  31. return src <= end-MINCODA;
  32. }
  33. }
  34. int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
  35. {
  36. if (out_size <= in_size || in_size < MINSRCSIZE)
  37. return -1;
  38. u8 const * src = static_cast<u8 const *>(in),
  39. * literal = 0,
  40. * const src_end = src + in_size;
  41. u8 * dst = static_cast<u8*>(out),
  42. * const dst_end = dst + out_size;
  43. // Check the in and out size hasn't wrapped around.
  44. if (src >= src_end || dst >= dst_end)
  45. return -1;
  46. u32 literal_len = 0,
  47. match_len = 0,
  48. match_dist = 0;
  49. while (read_sequence(src, src_end, literal, literal_len, match_len,
  50. match_dist))
  51. {
  52. if (literal_len != 0)
  53. {
  54. // Copy in literal. At this point the a minimal literal + minminal
  55. // match plus the coda (1 + 2 + 5) must be 8 bytes or more allowing
  56. // us to remain within the src buffer for an overrun_copy on
  57. // machines upto 64 bits.
  58. if (align(literal_len) > out_size)
  59. return -1;
  60. dst = overrun_copy(dst, literal, literal_len);
  61. out_size -= literal_len;
  62. }
  63. // Copy, possibly repeating, match from earlier in the
  64. // decoded output.
  65. u8 const * const pcpy = dst - match_dist;
  66. if (pcpy < static_cast<u8*>(out)
  67. || match_len > unsigned(out_size - LASTLITERALS)
  68. // Wrap around checks:
  69. || out_size < LASTLITERALS || pcpy >= dst)
  70. return -1;
  71. if (dst > pcpy+sizeof(unsigned long)
  72. && align(match_len) <= out_size)
  73. dst = overrun_copy(dst, pcpy, match_len);
  74. else
  75. dst = safe_copy(dst, pcpy, match_len);
  76. out_size -= match_len;
  77. }
  78. if (literal > src_end - literal_len || literal_len > out_size)
  79. return -1;
  80. dst = fast_copy(dst, literal, literal_len);
  81. return int(dst - (u8*)out);
  82. }