lzo1x_decompress_safe.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * LZO1X Decompressor from LZO
  3. *
  4. * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
  5. *
  6. * The full LZO package can be found at:
  7. * http://www.oberhumer.com/opensource/lzo/
  8. *
  9. * Changed for Linux kernel use by:
  10. * Nitin Gupta <nitingupta910@gmail.com>
  11. * Richard Purdie <rpurdie@openedhand.com>
  12. */
  13. #ifndef STATIC
  14. #include <linux/module.h>
  15. #include <linux/kernel.h>
  16. #endif
  17. #include <asm/unaligned.h>
  18. #include <linux/lzo.h>
  19. #include "lzodefs.h"
  20. #define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x))
  21. #define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x))
  22. #define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun
  23. #define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun
  24. #define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun
  25. /* This MAX_255_COUNT is the maximum number of times we can add 255 to a base
  26. * count without overflowing an integer. The multiply will overflow when
  27. * multiplying 255 by more than MAXINT/255. The sum will overflow earlier
  28. * depending on the base count. Since the base count is taken from a u8
  29. * and a few bits, it is safe to assume that it will always be lower than
  30. * or equal to 2*255, thus we can always prevent any overflow by accepting
  31. * two less 255 steps. See Documentation/lzo.txt for more information.
  32. */
  33. #define MAX_255_COUNT ((((size_t)~0) / 255) - 2)
  34. int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
  35. unsigned char *out, size_t *out_len)
  36. {
  37. unsigned char *op;
  38. const unsigned char *ip;
  39. size_t t, next;
  40. size_t state = 0;
  41. const unsigned char *m_pos;
  42. const unsigned char * const ip_end = in + in_len;
  43. unsigned char * const op_end = out + *out_len;
  44. op = out;
  45. ip = in;
  46. if (unlikely(in_len < 3))
  47. goto input_overrun;
  48. if (*ip > 17) {
  49. t = *ip++ - 17;
  50. if (t < 4) {
  51. next = t;
  52. goto match_next;
  53. }
  54. goto copy_literal_run;
  55. }
  56. for (;;) {
  57. t = *ip++;
  58. if (t < 16) {
  59. if (likely(state == 0)) {
  60. if (unlikely(t == 0)) {
  61. size_t offset;
  62. const unsigned char *ip_last = ip;
  63. while (unlikely(*ip == 0)) {
  64. ip++;
  65. NEED_IP(1);
  66. }
  67. offset = ip - ip_last;
  68. if (unlikely(offset > MAX_255_COUNT))
  69. return LZO_E_ERROR;
  70. offset = (offset << 8) - offset;
  71. t += offset + 15 + *ip++;
  72. }
  73. t += 3;
  74. copy_literal_run:
  75. #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
  76. if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) {
  77. const unsigned char *ie = ip + t;
  78. unsigned char *oe = op + t;
  79. do {
  80. COPY8(op, ip);
  81. op += 8;
  82. ip += 8;
  83. COPY8(op, ip);
  84. op += 8;
  85. ip += 8;
  86. } while (ip < ie);
  87. ip = ie;
  88. op = oe;
  89. } else
  90. #endif
  91. {
  92. NEED_OP(t);
  93. NEED_IP(t + 3);
  94. do {
  95. *op++ = *ip++;
  96. } while (--t > 0);
  97. }
  98. state = 4;
  99. continue;
  100. } else if (state != 4) {
  101. next = t & 3;
  102. m_pos = op - 1;
  103. m_pos -= t >> 2;
  104. m_pos -= *ip++ << 2;
  105. TEST_LB(m_pos);
  106. NEED_OP(2);
  107. op[0] = m_pos[0];
  108. op[1] = m_pos[1];
  109. op += 2;
  110. goto match_next;
  111. } else {
  112. next = t & 3;
  113. m_pos = op - (1 + M2_MAX_OFFSET);
  114. m_pos -= t >> 2;
  115. m_pos -= *ip++ << 2;
  116. t = 3;
  117. }
  118. } else if (t >= 64) {
  119. next = t & 3;
  120. m_pos = op - 1;
  121. m_pos -= (t >> 2) & 7;
  122. m_pos -= *ip++ << 3;
  123. t = (t >> 5) - 1 + (3 - 1);
  124. } else if (t >= 32) {
  125. t = (t & 31) + (3 - 1);
  126. if (unlikely(t == 2)) {
  127. size_t offset;
  128. const unsigned char *ip_last = ip;
  129. while (unlikely(*ip == 0)) {
  130. ip++;
  131. NEED_IP(1);
  132. }
  133. offset = ip - ip_last;
  134. if (unlikely(offset > MAX_255_COUNT))
  135. return LZO_E_ERROR;
  136. offset = (offset << 8) - offset;
  137. t += offset + 31 + *ip++;
  138. NEED_IP(2);
  139. }
  140. m_pos = op - 1;
  141. next = get_unaligned_le16(ip);
  142. ip += 2;
  143. m_pos -= next >> 2;
  144. next &= 3;
  145. } else {
  146. m_pos = op;
  147. m_pos -= (t & 8) << 11;
  148. t = (t & 7) + (3 - 1);
  149. if (unlikely(t == 2)) {
  150. size_t offset;
  151. const unsigned char *ip_last = ip;
  152. while (unlikely(*ip == 0)) {
  153. ip++;
  154. NEED_IP(1);
  155. }
  156. offset = ip - ip_last;
  157. if (unlikely(offset > MAX_255_COUNT))
  158. return LZO_E_ERROR;
  159. offset = (offset << 8) - offset;
  160. t += offset + 7 + *ip++;
  161. NEED_IP(2);
  162. }
  163. next = get_unaligned_le16(ip);
  164. ip += 2;
  165. m_pos -= next >> 2;
  166. next &= 3;
  167. if (m_pos == op)
  168. goto eof_found;
  169. m_pos -= 0x4000;
  170. }
  171. TEST_LB(m_pos);
  172. #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
  173. if (op - m_pos >= 8) {
  174. unsigned char *oe = op + t;
  175. if (likely(HAVE_OP(t + 15))) {
  176. do {
  177. COPY8(op, m_pos);
  178. op += 8;
  179. m_pos += 8;
  180. COPY8(op, m_pos);
  181. op += 8;
  182. m_pos += 8;
  183. } while (op < oe);
  184. op = oe;
  185. if (HAVE_IP(6)) {
  186. state = next;
  187. COPY4(op, ip);
  188. op += next;
  189. ip += next;
  190. continue;
  191. }
  192. } else {
  193. NEED_OP(t);
  194. do {
  195. *op++ = *m_pos++;
  196. } while (op < oe);
  197. }
  198. } else
  199. #endif
  200. {
  201. unsigned char *oe = op + t;
  202. NEED_OP(t);
  203. op[0] = m_pos[0];
  204. op[1] = m_pos[1];
  205. op += 2;
  206. m_pos += 2;
  207. do {
  208. *op++ = *m_pos++;
  209. } while (op < oe);
  210. }
  211. match_next:
  212. state = next;
  213. t = next;
  214. #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
  215. if (likely(HAVE_IP(6) && HAVE_OP(4))) {
  216. COPY4(op, ip);
  217. op += t;
  218. ip += t;
  219. } else
  220. #endif
  221. {
  222. NEED_IP(t + 3);
  223. NEED_OP(t);
  224. while (t > 0) {
  225. *op++ = *ip++;
  226. t--;
  227. }
  228. }
  229. }
  230. eof_found:
  231. *out_len = op - out;
  232. return (t != 3 ? LZO_E_ERROR :
  233. ip == ip_end ? LZO_E_OK :
  234. ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN);
  235. input_overrun:
  236. *out_len = op - out;
  237. return LZO_E_INPUT_OVERRUN;
  238. output_overrun:
  239. *out_len = op - out;
  240. return LZO_E_OUTPUT_OVERRUN;
  241. lookbehind_overrun:
  242. *out_len = op - out;
  243. return LZO_E_LOOKBEHIND_OVERRUN;
  244. }
  245. #ifndef STATIC
  246. EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
  247. MODULE_LICENSE("GPL");
  248. MODULE_DESCRIPTION("LZO1X Decompressor");
  249. #endif