lzo1x_decompress_safe.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. # if !defined(__arm__)
  84. COPY8(op, ip);
  85. op += 8;
  86. ip += 8;
  87. # endif
  88. } while (ip < ie);
  89. ip = ie;
  90. op = oe;
  91. } else
  92. #endif
  93. {
  94. NEED_OP(t);
  95. NEED_IP(t + 3);
  96. do {
  97. *op++ = *ip++;
  98. } while (--t > 0);
  99. }
  100. state = 4;
  101. continue;
  102. } else if (state != 4) {
  103. next = t & 3;
  104. m_pos = op - 1;
  105. m_pos -= t >> 2;
  106. m_pos -= *ip++ << 2;
  107. TEST_LB(m_pos);
  108. NEED_OP(2);
  109. op[0] = m_pos[0];
  110. op[1] = m_pos[1];
  111. op += 2;
  112. goto match_next;
  113. } else {
  114. next = t & 3;
  115. m_pos = op - (1 + M2_MAX_OFFSET);
  116. m_pos -= t >> 2;
  117. m_pos -= *ip++ << 2;
  118. t = 3;
  119. }
  120. } else if (t >= 64) {
  121. next = t & 3;
  122. m_pos = op - 1;
  123. m_pos -= (t >> 2) & 7;
  124. m_pos -= *ip++ << 3;
  125. t = (t >> 5) - 1 + (3 - 1);
  126. } else if (t >= 32) {
  127. t = (t & 31) + (3 - 1);
  128. if (unlikely(t == 2)) {
  129. size_t offset;
  130. const unsigned char *ip_last = ip;
  131. while (unlikely(*ip == 0)) {
  132. ip++;
  133. NEED_IP(1);
  134. }
  135. offset = ip - ip_last;
  136. if (unlikely(offset > MAX_255_COUNT))
  137. return LZO_E_ERROR;
  138. offset = (offset << 8) - offset;
  139. t += offset + 31 + *ip++;
  140. NEED_IP(2);
  141. }
  142. m_pos = op - 1;
  143. next = get_unaligned_le16(ip);
  144. ip += 2;
  145. m_pos -= next >> 2;
  146. next &= 3;
  147. } else {
  148. m_pos = op;
  149. m_pos -= (t & 8) << 11;
  150. t = (t & 7) + (3 - 1);
  151. if (unlikely(t == 2)) {
  152. size_t offset;
  153. const unsigned char *ip_last = ip;
  154. while (unlikely(*ip == 0)) {
  155. ip++;
  156. NEED_IP(1);
  157. }
  158. offset = ip - ip_last;
  159. if (unlikely(offset > MAX_255_COUNT))
  160. return LZO_E_ERROR;
  161. offset = (offset << 8) - offset;
  162. t += offset + 7 + *ip++;
  163. NEED_IP(2);
  164. }
  165. next = get_unaligned_le16(ip);
  166. ip += 2;
  167. m_pos -= next >> 2;
  168. next &= 3;
  169. if (m_pos == op)
  170. goto eof_found;
  171. m_pos -= 0x4000;
  172. }
  173. TEST_LB(m_pos);
  174. #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
  175. if (op - m_pos >= 8) {
  176. unsigned char *oe = op + t;
  177. if (likely(HAVE_OP(t + 15))) {
  178. do {
  179. COPY8(op, m_pos);
  180. op += 8;
  181. m_pos += 8;
  182. # if !defined(__arm__)
  183. COPY8(op, m_pos);
  184. op += 8;
  185. m_pos += 8;
  186. # endif
  187. } while (op < oe);
  188. op = oe;
  189. if (HAVE_IP(6)) {
  190. state = next;
  191. COPY4(op, ip);
  192. op += next;
  193. ip += next;
  194. continue;
  195. }
  196. } else {
  197. NEED_OP(t);
  198. do {
  199. *op++ = *m_pos++;
  200. } while (op < oe);
  201. }
  202. } else
  203. #endif
  204. {
  205. unsigned char *oe = op + t;
  206. NEED_OP(t);
  207. op[0] = m_pos[0];
  208. op[1] = m_pos[1];
  209. op += 2;
  210. m_pos += 2;
  211. do {
  212. *op++ = *m_pos++;
  213. } while (op < oe);
  214. }
  215. match_next:
  216. state = next;
  217. t = next;
  218. #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
  219. if (likely(HAVE_IP(6) && HAVE_OP(4))) {
  220. COPY4(op, ip);
  221. op += t;
  222. ip += t;
  223. } else
  224. #endif
  225. {
  226. NEED_IP(t + 3);
  227. NEED_OP(t);
  228. while (t > 0) {
  229. *op++ = *ip++;
  230. t--;
  231. }
  232. }
  233. }
  234. eof_found:
  235. *out_len = op - out;
  236. return (t != 3 ? LZO_E_ERROR :
  237. ip == ip_end ? LZO_E_OK :
  238. ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN);
  239. input_overrun:
  240. *out_len = op - out;
  241. return LZO_E_INPUT_OVERRUN;
  242. output_overrun:
  243. *out_len = op - out;
  244. return LZO_E_OUTPUT_OVERRUN;
  245. lookbehind_overrun:
  246. *out_len = op - out;
  247. return LZO_E_LOOKBEHIND_OVERRUN;
  248. }
  249. #ifndef STATIC
  250. EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
  251. MODULE_LICENSE("GPL");
  252. MODULE_DESCRIPTION("LZO1X Decompressor");
  253. #endif