lzo1x_d.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /* implementation of the LZO1X decompression algorithm
  2. This file is part of the LZO real-time data compression library.
  3. Copyright (C) 1996..2008 Markus Franz Xaver Johannes Oberhumer
  4. All Rights Reserved.
  5. Markus F.X.J. Oberhumer <markus@oberhumer.com>
  6. http://www.oberhumer.com/opensource/lzo/
  7. The LZO library is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License as
  9. published by the Free Software Foundation; either version 2 of
  10. the License, or (at your option) any later version.
  11. The LZO library is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with the LZO library; see the file COPYING.
  17. If not, write to the Free Software Foundation, Inc.,
  18. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. #include "libbb.h"
  21. #include "liblzo.h"
  22. /***********************************************************************
  23. // decompress a block of data.
  24. ************************************************************************/
  25. /* safe decompression with overrun testing */
  26. int lzo1x_decompress_safe(const uint8_t* in, unsigned in_len,
  27. uint8_t* out, unsigned* out_len,
  28. void* wrkmem UNUSED_PARAM)
  29. {
  30. register uint8_t* op;
  31. register const uint8_t* ip;
  32. register unsigned t;
  33. #if defined(COPY_DICT)
  34. unsigned m_off;
  35. const uint8_t* dict_end;
  36. #else
  37. register const uint8_t* m_pos = NULL; /* possibly not needed */
  38. #endif
  39. const uint8_t* const ip_end = in + in_len;
  40. #if defined(HAVE_ANY_OP)
  41. uint8_t* const op_end = out + *out_len;
  42. #endif
  43. #if defined(LZO1Z)
  44. unsigned last_m_off = 0;
  45. #endif
  46. // LZO_UNUSED(wrkmem);
  47. #if defined(COPY_DICT)
  48. if (dict) {
  49. if (dict_len > M4_MAX_OFFSET) {
  50. dict += dict_len - M4_MAX_OFFSET;
  51. dict_len = M4_MAX_OFFSET;
  52. }
  53. dict_end = dict + dict_len;
  54. } else {
  55. dict_len = 0;
  56. dict_end = NULL;
  57. }
  58. #endif /* COPY_DICT */
  59. *out_len = 0;
  60. op = out;
  61. ip = in;
  62. if (*ip > 17) {
  63. t = *ip++ - 17;
  64. if (t < 4)
  65. goto match_next;
  66. assert(t > 0); NEED_OP(t); NEED_IP(t+1);
  67. do *op++ = *ip++; while (--t > 0);
  68. goto first_literal_run;
  69. }
  70. while (TEST_IP && TEST_OP) {
  71. t = *ip++;
  72. if (t >= 16)
  73. goto match;
  74. /* a literal run */
  75. if (t == 0) {
  76. NEED_IP(1);
  77. while (*ip == 0) {
  78. t += 255;
  79. ip++;
  80. NEED_IP(1);
  81. }
  82. TEST_IV(t);
  83. t += 15 + *ip++;
  84. }
  85. /* copy literals */
  86. assert(t > 0);
  87. NEED_OP(t+3);
  88. NEED_IP(t+4);
  89. #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
  90. # if !defined(LZO_UNALIGNED_OK_4)
  91. if (PTR_ALIGNED2_4(op, ip))
  92. # endif
  93. {
  94. COPY4(op, ip);
  95. op += 4;
  96. ip += 4;
  97. if (--t > 0) {
  98. if (t >= 4) {
  99. do {
  100. COPY4(op, ip);
  101. op += 4;
  102. ip += 4;
  103. t -= 4;
  104. } while (t >= 4);
  105. if (t > 0)
  106. do *op++ = *ip++; while (--t > 0);
  107. } else {
  108. do *op++ = *ip++; while (--t > 0);
  109. }
  110. }
  111. }
  112. # if !defined(LZO_UNALIGNED_OK_4)
  113. else
  114. # endif
  115. #endif
  116. #if !defined(LZO_UNALIGNED_OK_4)
  117. {
  118. *op++ = *ip++;
  119. *op++ = *ip++;
  120. *op++ = *ip++;
  121. do *op++ = *ip++; while (--t > 0);
  122. }
  123. #endif
  124. first_literal_run:
  125. t = *ip++;
  126. if (t >= 16)
  127. goto match;
  128. #if defined(COPY_DICT)
  129. #if defined(LZO1Z)
  130. m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
  131. last_m_off = m_off;
  132. #else
  133. m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
  134. #endif
  135. NEED_OP(3);
  136. t = 3; COPY_DICT(t,m_off)
  137. #else /* !COPY_DICT */
  138. #if defined(LZO1Z)
  139. t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
  140. m_pos = op - t;
  141. last_m_off = t;
  142. #else
  143. m_pos = op - (1 + M2_MAX_OFFSET);
  144. m_pos -= t >> 2;
  145. m_pos -= *ip++ << 2;
  146. #endif
  147. TEST_LB(m_pos); NEED_OP(3);
  148. *op++ = *m_pos++;
  149. *op++ = *m_pos++;
  150. *op++ = *m_pos;
  151. #endif /* COPY_DICT */
  152. goto match_done;
  153. /* handle matches */
  154. do {
  155. match:
  156. if (t >= 64) { /* a M2 match */
  157. #if defined(COPY_DICT)
  158. #if defined(LZO1X)
  159. m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
  160. t = (t >> 5) - 1;
  161. #elif defined(LZO1Y)
  162. m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
  163. t = (t >> 4) - 3;
  164. #elif defined(LZO1Z)
  165. m_off = t & 0x1f;
  166. if (m_off >= 0x1c)
  167. m_off = last_m_off;
  168. else {
  169. m_off = 1 + (m_off << 6) + (*ip++ >> 2);
  170. last_m_off = m_off;
  171. }
  172. t = (t >> 5) - 1;
  173. #endif
  174. #else /* !COPY_DICT */
  175. #if defined(LZO1X)
  176. m_pos = op - 1;
  177. m_pos -= (t >> 2) & 7;
  178. m_pos -= *ip++ << 3;
  179. t = (t >> 5) - 1;
  180. #elif defined(LZO1Y)
  181. m_pos = op - 1;
  182. m_pos -= (t >> 2) & 3;
  183. m_pos -= *ip++ << 2;
  184. t = (t >> 4) - 3;
  185. #elif defined(LZO1Z)
  186. {
  187. unsigned off = t & 0x1f;
  188. m_pos = op;
  189. if (off >= 0x1c) {
  190. assert(last_m_off > 0);
  191. m_pos -= last_m_off;
  192. } else {
  193. off = 1 + (off << 6) + (*ip++ >> 2);
  194. m_pos -= off;
  195. last_m_off = off;
  196. }
  197. }
  198. t = (t >> 5) - 1;
  199. #endif
  200. TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
  201. goto copy_match;
  202. #endif /* COPY_DICT */
  203. }
  204. else if (t >= 32) { /* a M3 match */
  205. t &= 31;
  206. if (t == 0) {
  207. NEED_IP(1);
  208. while (*ip == 0) {
  209. t += 255;
  210. ip++;
  211. NEED_IP(1);
  212. }
  213. TEST_IV(t);
  214. t += 31 + *ip++;
  215. }
  216. #if defined(COPY_DICT)
  217. #if defined(LZO1Z)
  218. m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
  219. last_m_off = m_off;
  220. #else
  221. m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
  222. #endif
  223. #else /* !COPY_DICT */
  224. #if defined(LZO1Z)
  225. {
  226. unsigned off = 1 + (ip[0] << 6) + (ip[1] >> 2);
  227. m_pos = op - off;
  228. last_m_off = off;
  229. }
  230. #elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
  231. m_pos = op - 1;
  232. m_pos -= (* (const lzo_ushortp) ip) >> 2;
  233. #else
  234. m_pos = op - 1;
  235. m_pos -= (ip[0] >> 2) + (ip[1] << 6);
  236. #endif
  237. #endif /* COPY_DICT */
  238. ip += 2;
  239. }
  240. else if (t >= 16) { /* a M4 match */
  241. #if defined(COPY_DICT)
  242. m_off = (t & 8) << 11;
  243. #else /* !COPY_DICT */
  244. m_pos = op;
  245. m_pos -= (t & 8) << 11;
  246. #endif /* COPY_DICT */
  247. t &= 7;
  248. if (t == 0) {
  249. NEED_IP(1);
  250. while (*ip == 0) {
  251. t += 255;
  252. ip++;
  253. NEED_IP(1);
  254. }
  255. TEST_IV(t);
  256. t += 7 + *ip++;
  257. }
  258. #if defined(COPY_DICT)
  259. #if defined(LZO1Z)
  260. m_off += (ip[0] << 6) + (ip[1] >> 2);
  261. #else
  262. m_off += (ip[0] >> 2) + (ip[1] << 6);
  263. #endif
  264. ip += 2;
  265. if (m_off == 0)
  266. goto eof_found;
  267. m_off += 0x4000;
  268. #if defined(LZO1Z)
  269. last_m_off = m_off;
  270. #endif
  271. #else /* !COPY_DICT */
  272. #if defined(LZO1Z)
  273. m_pos -= (ip[0] << 6) + (ip[1] >> 2);
  274. #elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
  275. m_pos -= (* (const lzo_ushortp) ip) >> 2;
  276. #else
  277. m_pos -= (ip[0] >> 2) + (ip[1] << 6);
  278. #endif
  279. ip += 2;
  280. if (m_pos == op)
  281. goto eof_found;
  282. m_pos -= 0x4000;
  283. #if defined(LZO1Z)
  284. last_m_off = pd((const uint8_t*)op, m_pos);
  285. #endif
  286. #endif /* COPY_DICT */
  287. }
  288. else { /* a M1 match */
  289. #if defined(COPY_DICT)
  290. #if defined(LZO1Z)
  291. m_off = 1 + (t << 6) + (*ip++ >> 2);
  292. last_m_off = m_off;
  293. #else
  294. m_off = 1 + (t >> 2) + (*ip++ << 2);
  295. #endif
  296. NEED_OP(2);
  297. t = 2; COPY_DICT(t,m_off)
  298. #else /* !COPY_DICT */
  299. #if defined(LZO1Z)
  300. t = 1 + (t << 6) + (*ip++ >> 2);
  301. m_pos = op - t;
  302. last_m_off = t;
  303. #else
  304. m_pos = op - 1;
  305. m_pos -= t >> 2;
  306. m_pos -= *ip++ << 2;
  307. #endif
  308. TEST_LB(m_pos); NEED_OP(2);
  309. *op++ = *m_pos++;
  310. *op++ = *m_pos;
  311. #endif /* COPY_DICT */
  312. goto match_done;
  313. }
  314. /* copy match */
  315. #if defined(COPY_DICT)
  316. NEED_OP(t+3-1);
  317. t += 3-1; COPY_DICT(t,m_off)
  318. #else /* !COPY_DICT */
  319. TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
  320. #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
  321. # if !defined(LZO_UNALIGNED_OK_4)
  322. if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) {
  323. assert((op - m_pos) >= 4); /* both pointers are aligned */
  324. # else
  325. if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
  326. # endif
  327. COPY4(op,m_pos);
  328. op += 4; m_pos += 4; t -= 4 - (3 - 1);
  329. do {
  330. COPY4(op,m_pos);
  331. op += 4; m_pos += 4; t -= 4;
  332. } while (t >= 4);
  333. if (t > 0)
  334. do *op++ = *m_pos++; while (--t > 0);
  335. }
  336. else
  337. #endif
  338. {
  339. copy_match:
  340. *op++ = *m_pos++; *op++ = *m_pos++;
  341. do *op++ = *m_pos++; while (--t > 0);
  342. }
  343. #endif /* COPY_DICT */
  344. match_done:
  345. #if defined(LZO1Z)
  346. t = ip[-1] & 3;
  347. #else
  348. t = ip[-2] & 3;
  349. #endif
  350. if (t == 0)
  351. break;
  352. /* copy literals */
  353. match_next:
  354. assert(t > 0);
  355. assert(t < 4);
  356. NEED_OP(t);
  357. NEED_IP(t+1);
  358. #if 0
  359. do *op++ = *ip++; while (--t > 0);
  360. #else
  361. *op++ = *ip++;
  362. if (t > 1) {
  363. *op++ = *ip++;
  364. if (t > 2)
  365. *op++ = *ip++;
  366. }
  367. #endif
  368. t = *ip++;
  369. } while (TEST_IP && TEST_OP);
  370. }
  371. //#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
  372. /* no EOF code was found */
  373. *out_len = pd(op, out);
  374. return LZO_E_EOF_NOT_FOUND;
  375. //#endif
  376. eof_found:
  377. assert(t == 1);
  378. *out_len = pd(op, out);
  379. return (ip == ip_end ? LZO_E_OK :
  380. (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
  381. //#if defined(HAVE_NEED_IP)
  382. input_overrun:
  383. *out_len = pd(op, out);
  384. return LZO_E_INPUT_OVERRUN;
  385. //#endif
  386. //#if defined(HAVE_NEED_OP)
  387. output_overrun:
  388. *out_len = pd(op, out);
  389. return LZO_E_OUTPUT_OVERRUN;
  390. //#endif
  391. //#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
  392. lookbehind_overrun:
  393. *out_len = pd(op, out);
  394. return LZO_E_LOOKBEHIND_OVERRUN;
  395. //#endif
  396. }