PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/LZ4Sharp/LZ4Decompressor.c

http://github.com/stangelandcl/LZ4Sharp
C | 273 lines | 201 code | 44 blank | 28 comment | 44 complexity | d1d40f71dee9d58baad1741b1c014ed6 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Diagnostics;
  6. namespace LZ4Sharp
  7. {
  8. #if LZ4_ARCH64
  9. #define CLASSNAME LZ4Decompressor64
  10. #else
  11. #define CLASSNAME LZ4Decompressor32
  12. #endif
  13. /// <summary>
  14. /// Class for decompressing an LZ4 compressed byte array.
  15. /// </summary>
  16. public unsafe class CLASSNAME : ILZ4Decompressor
  17. {
  18. #include "LZ4.h"
  19. readonly sbyte[] m_DecArray = new sbyte[8] { 0, 3, 2, 3,0,0,0,0 };
  20. #if LZ4_ARCH64
  21. readonly sbyte[] m_Dec2table= new sbyte[8]{0, 0, 0, -1, 0, 1, 2, 3};
  22. #endif
  23. // Note : The decoding functions LZ4_uncompress() and LZ4_uncompress_unknownOutputSize()
  24. // are safe against "buffer overflow" attack type
  25. // since they will *never* write outside of the provided output buffer :
  26. // they both check this condition *before* writing anything.
  27. // A corrupted packet however can make them *read* within the first 64K before the output buffer.
  28. /// <summary>
  29. /// Decompress.
  30. /// </summary>
  31. /// <param name="source">compressed array</param>
  32. /// <param name="dest">This must be the exact length of the decompressed item</param>
  33. public void DecompressKnownSize(byte[] compressed, byte[] decompressed)
  34. {
  35. int len = DecompressKnownSize(compressed, decompressed, decompressed.Length);
  36. Debug.Assert(len == decompressed.Length);
  37. }
  38. public int DecompressKnownSize(byte[] compressed, byte[] decompressedBuffer, int decompressedSize)
  39. {
  40. fixed (byte* src = compressed)
  41. fixed (byte* dst = decompressedBuffer)
  42. return DecompressKnownSize(src, dst, decompressedSize);
  43. }
  44. public int DecompressKnownSize(byte* compressed, byte* decompressedBuffer, int decompressedSize)
  45. {
  46. fixed (sbyte* dec = m_DecArray)
  47. #if LZ4_ARCH64
  48. fixed(sbyte* dec2Ptr = m_Dec2table)
  49. #endif
  50. {
  51. // Local Variables
  52. byte* ip = (byte*)compressed;
  53. byte* r;
  54. byte* op = (byte*)decompressedBuffer;
  55. byte* oend = op + decompressedSize;
  56. byte* cpy;
  57. byte token;
  58. int len, length;
  59. // Main Loop
  60. while (true)
  61. {
  62. // get runLength
  63. token = *ip++;
  64. if ((length = (token >> LZ4Util.ML_BITS)) == LZ4Util.RUN_MASK) { for (; (len = *ip++) == 255; length += 255) { } length += len; }
  65. cpy = op + length;
  66. if (cpy > oend - LZ4Util.COPYLENGTH)
  67. {
  68. if (cpy > oend) goto _output_error;
  69. LZ4Util.CopyMemory(op, ip, length);
  70. ip += length;
  71. break;
  72. }
  73. LZ4_WILDCOPY(ip, op, cpy); ip -= (op - cpy); op = cpy;
  74. // get offset
  75. LZ4_READ_LITTLEENDIAN_16(r,cpy,ip); ip+=2;
  76. if(r < decompressedBuffer) goto _output_error;
  77. // get matchLength
  78. if ((length = (int)(token & LZ4Util.ML_MASK)) == LZ4Util.ML_MASK) { for (; *ip == 255; length += 255) { ip++; } length += *ip++; }
  79. // copy repeated sequence
  80. if (op - r < STEPSIZE)
  81. {
  82. #if LZ4_ARCH64
  83. var dec2 = dec2Ptr[(int)(op-r)];
  84. #else
  85. const int dec2 = 0;
  86. #endif
  87. *op++ = *r++;
  88. *op++ = *r++;
  89. *op++ = *r++;
  90. *op++ = *r++;
  91. r -= dec[op - r];
  92. A32(op) = A32(r); op += STEPSIZE - 4;
  93. r -= dec2;
  94. }
  95. else { LZ4_COPYSTEP(r, op); }
  96. cpy = op + length - (STEPSIZE - 4);
  97. if (cpy > oend - LZ4Util.COPYLENGTH)
  98. {
  99. if (cpy > oend) goto _output_error;
  100. LZ4_SECURECOPY(r, op, (oend - LZ4Util.COPYLENGTH));
  101. while (op < cpy) *op++ = *r++;
  102. op = cpy;
  103. if (op == oend) break;
  104. continue;
  105. }
  106. LZ4_SECURECOPY(r, op, cpy);
  107. op = cpy; // correction
  108. }
  109. // end of decoding
  110. return (int)(((byte*)ip) - compressed);
  111. // write overflow error detected
  112. _output_error:
  113. return (int)(-(((byte*)ip) - compressed));
  114. }
  115. }
  116. public byte[] Decompress(byte[] compressed)
  117. {
  118. int length = compressed.Length;
  119. int len;
  120. byte[] dest;
  121. const int Multiplier = 4; // Just a number. Determines how fast length should increase.
  122. do
  123. {
  124. length *= Multiplier;
  125. dest = new byte[length];
  126. len = Decompress(compressed, dest, compressed.Length);
  127. }
  128. while (len < 0 || dest.Length < len);
  129. byte[] d = new byte[len];
  130. Buffer.BlockCopy(dest, 0, d, 0, d.Length);
  131. return d;
  132. }
  133. public int Decompress(byte[] compressed, byte[] decompressedBuffer)
  134. {
  135. return Decompress(compressed, decompressedBuffer, compressed.Length);
  136. }
  137. public int Decompress(byte[] compressedBuffer, byte[] decompressedBuffer, int compressedSize)
  138. {
  139. fixed (byte* src = compressedBuffer)
  140. fixed (byte* dst = decompressedBuffer)
  141. return Decompress(src, dst, compressedSize, decompressedBuffer.Length);
  142. }
  143. public int Decompress(byte[] compressedBuffer, int compressedPosition, byte[] decompressedBuffer, int decompressedPosition, int compressedSize)
  144. {
  145. fixed (byte* src = &compressedBuffer[compressedPosition])
  146. fixed (byte* dst = &decompressedBuffer[decompressedPosition])
  147. return Decompress(src, dst, compressedSize, decompressedBuffer.Length);
  148. }
  149. public int Decompress(
  150. byte* compressedBuffer,
  151. byte* decompressedBuffer,
  152. int compressedSize,
  153. int maxDecompressedSize)
  154. {
  155. fixed (sbyte* dec = m_DecArray)
  156. #if LZ4_ARCH64
  157. fixed(sbyte* dec2Ptr = m_Dec2table)
  158. #endif
  159. {
  160. // Local Variables
  161. byte* ip = (byte*)compressedBuffer;
  162. byte* iend = ip + compressedSize;
  163. byte* r;
  164. byte* op = (byte*)decompressedBuffer;
  165. byte* oend = op + maxDecompressedSize;
  166. byte* cpy;
  167. byte token;
  168. int len, length;
  169. // Main Loop
  170. while (ip < iend)
  171. {
  172. // get runLength
  173. token = *ip++;
  174. if ((length=(token>>LZ4Util.ML_BITS)) == LZ4Util.RUN_MASK) { int s=255; while ((ip<iend) && (s==255)) { s=*ip++; length += s; } }
  175. // copy literals
  176. cpy = op + length;
  177. if ((cpy>oend-LZ4Util.COPYLENGTH) || (ip+length>iend-LZ4Util.COPYLENGTH))
  178. {
  179. if (cpy > oend) goto _output_error; // Error : request to write beyond destination buffer
  180. if (ip+length > iend) goto _output_error; // Error : request to read beyond source buffer
  181. LZ4Util.CopyMemory(op, ip, length);
  182. op += length;
  183. ip += length;
  184. if (ip<iend) goto _output_error; // Error : LZ4 format violation
  185. break; //Necessarily EOF
  186. }
  187. LZ4_WILDCOPY(ip, op, cpy); ip -= (op - cpy); op = cpy;
  188. // get offset
  189. LZ4_READ_LITTLEENDIAN_16(r,cpy,ip); ip+=2;
  190. if (r < decompressedBuffer) goto _output_error;
  191. // get matchlength
  192. if ((length=(int)(token&LZ4Util.ML_MASK)) == LZ4Util.ML_MASK) { while (ip<iend) { int s = *ip++; length +=s; if (s==255) continue; break; } }
  193. // copy repeated sequence
  194. if (op - r < STEPSIZE)
  195. {
  196. #if LZ4_ARCH64
  197. var dec2 = dec2Ptr[op-ref];
  198. #else
  199. const int dec2 = 0;
  200. #endif
  201. *op++ = *r++;
  202. *op++ = *r++;
  203. *op++ = *r++;
  204. *op++ = *r++;
  205. r -= dec[op - r];
  206. A32(op) = A32(r); op += STEPSIZE - 4;
  207. r -= dec2;
  208. }
  209. else { LZ4_COPYSTEP(r, op); }
  210. cpy = op + length - (STEPSIZE - 4);
  211. if (cpy > oend - LZ4Util.COPYLENGTH)
  212. {
  213. if (cpy > oend) goto _output_error;
  214. LZ4_SECURECOPY(r, op, (oend - LZ4Util.COPYLENGTH));
  215. while (op < cpy) *op++ = *r++;
  216. op = cpy;
  217. if (op == oend) goto _output_error; // Check EOF (should never happen, since last 5 bytes are supposed to be literals)
  218. continue;
  219. }
  220. LZ4_SECURECOPY(r, op, cpy);
  221. op = cpy; // correction
  222. }
  223. return (int)(((byte*)op) - decompressedBuffer);
  224. _output_error:
  225. return (int)(-(((byte*)ip) - compressedBuffer));
  226. }
  227. }
  228. }
  229. }