lzo1x_d.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  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. t += 15 + *ip++;
  83. }
  84. /* copy literals */
  85. assert(t > 0);
  86. NEED_OP(t+3);
  87. NEED_IP(t+4);
  88. #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
  89. # if !defined(LZO_UNALIGNED_OK_4)
  90. if (PTR_ALIGNED2_4(op, ip))
  91. # endif
  92. {
  93. COPY4(op, ip);
  94. op += 4;
  95. ip += 4;
  96. if (--t > 0) {
  97. if (t >= 4) {
  98. do {
  99. COPY4(op, ip);
  100. op += 4;
  101. ip += 4;
  102. t -= 4;
  103. } while (t >= 4);
  104. if (t > 0)
  105. do *op++ = *ip++; while (--t > 0);
  106. } else {
  107. do *op++ = *ip++; while (--t > 0);
  108. }
  109. }
  110. }
  111. # if !defined(LZO_UNALIGNED_OK_4)
  112. else
  113. # endif
  114. #endif
  115. #if !defined(LZO_UNALIGNED_OK_4)
  116. {
  117. *op++ = *ip++;
  118. *op++ = *ip++;
  119. *op++ = *ip++;
  120. do *op++ = *ip++; while (--t > 0);
  121. }
  122. #endif
  123. first_literal_run:
  124. t = *ip++;
  125. if (t >= 16)
  126. goto match;
  127. #if defined(COPY_DICT)
  128. #if defined(LZO1Z)
  129. m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
  130. last_m_off = m_off;
  131. #else
  132. m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
  133. #endif
  134. NEED_OP(3);
  135. t = 3; COPY_DICT(t,m_off)
  136. #else /* !COPY_DICT */
  137. #if defined(LZO1Z)
  138. t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
  139. m_pos = op - t;
  140. last_m_off = t;
  141. #else
  142. m_pos = op - (1 + M2_MAX_OFFSET);
  143. m_pos -= t >> 2;
  144. m_pos -= *ip++ << 2;
  145. #endif
  146. TEST_LB(m_pos); NEED_OP(3);
  147. *op++ = *m_pos++;
  148. *op++ = *m_pos++;
  149. *op++ = *m_pos;
  150. #endif /* COPY_DICT */
  151. goto match_done;
  152. /* handle matches */
  153. do {
  154. match:
  155. if (t >= 64) { /* a M2 match */
  156. #if defined(COPY_DICT)
  157. #if defined(LZO1X)
  158. m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
  159. t = (t >> 5) - 1;
  160. #elif defined(LZO1Y)
  161. m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
  162. t = (t >> 4) - 3;
  163. #elif defined(LZO1Z)
  164. m_off = t & 0x1f;
  165. if (m_off >= 0x1c)
  166. m_off = last_m_off;
  167. else {
  168. m_off = 1 + (m_off << 6) + (*ip++ >> 2);
  169. last_m_off = m_off;
  170. }
  171. t = (t >> 5) - 1;
  172. #endif
  173. #else /* !COPY_DICT */
  174. #if defined(LZO1X)
  175. m_pos = op - 1;
  176. m_pos -= (t >> 2) & 7;
  177. m_pos -= *ip++ << 3;
  178. t = (t >> 5) - 1;
  179. #elif defined(LZO1Y)
  180. m_pos = op - 1;
  181. m_pos -= (t >> 2) & 3;
  182. m_pos -= *ip++ << 2;
  183. t = (t >> 4) - 3;
  184. #elif defined(LZO1Z)
  185. {
  186. unsigned off = t & 0x1f;
  187. m_pos = op;
  188. if (off >= 0x1c) {
  189. assert(last_m_off > 0);
  190. m_pos -= last_m_off;
  191. } else {
  192. off = 1 + (off << 6) + (*ip++ >> 2);
  193. m_pos -= off;
  194. last_m_off = off;
  195. }
  196. }
  197. t = (t >> 5) - 1;
  198. #endif
  199. TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
  200. goto copy_match;
  201. #endif /* COPY_DICT */
  202. }
  203. else if (t >= 32) { /* a M3 match */
  204. t &= 31;
  205. if (t == 0) {
  206. NEED_IP(1);
  207. while (*ip == 0) {
  208. t += 255;
  209. ip++;
  210. NEED_IP(1);
  211. }
  212. t += 31 + *ip++;
  213. }
  214. #if defined(COPY_DICT)
  215. #if defined(LZO1Z)
  216. m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
  217. last_m_off = m_off;
  218. #else
  219. m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
  220. #endif
  221. #else /* !COPY_DICT */
  222. #if defined(LZO1Z)
  223. {
  224. unsigned off = 1 + (ip[0] << 6) + (ip[1] >> 2);
  225. m_pos = op - off;
  226. last_m_off = off;
  227. }
  228. #elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
  229. m_pos = op - 1;
  230. m_pos -= (* (const lzo_ushortp) ip) >> 2;
  231. #else
  232. m_pos = op - 1;
  233. m_pos -= (ip[0] >> 2) + (ip[1] << 6);
  234. #endif
  235. #endif /* COPY_DICT */
  236. ip += 2;
  237. }
  238. else if (t >= 16) { /* a M4 match */
  239. #if defined(COPY_DICT)
  240. m_off = (t & 8) << 11;
  241. #else /* !COPY_DICT */
  242. m_pos = op;
  243. m_pos -= (t & 8) << 11;
  244. #endif /* COPY_DICT */
  245. t &= 7;
  246. if (t == 0) {
  247. NEED_IP(1);
  248. while (*ip == 0) {
  249. t += 255;
  250. ip++;
  251. NEED_IP(1);
  252. }
  253. t += 7 + *ip++;
  254. }
  255. #if defined(COPY_DICT)
  256. #if defined(LZO1Z)
  257. m_off += (ip[0] << 6) + (ip[1] >> 2);
  258. #else
  259. m_off += (ip[0] >> 2) + (ip[1] << 6);
  260. #endif
  261. ip += 2;
  262. if (m_off == 0)
  263. goto eof_found;
  264. m_off += 0x4000;
  265. #if defined(LZO1Z)
  266. last_m_off = m_off;
  267. #endif
  268. #else /* !COPY_DICT */
  269. #if defined(LZO1Z)
  270. m_pos -= (ip[0] << 6) + (ip[1] >> 2);
  271. #elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
  272. m_pos -= (* (const lzo_ushortp) ip) >> 2;
  273. #else
  274. m_pos -= (ip[0] >> 2) + (ip[1] << 6);
  275. #endif
  276. ip += 2;
  277. if (m_pos == op)
  278. goto eof_found;
  279. m_pos -= 0x4000;
  280. #if defined(LZO1Z)
  281. last_m_off = pd((const uint8_t*)op, m_pos);
  282. #endif
  283. #endif /* COPY_DICT */
  284. }
  285. else { /* a M1 match */
  286. #if defined(COPY_DICT)
  287. #if defined(LZO1Z)
  288. m_off = 1 + (t << 6) + (*ip++ >> 2);
  289. last_m_off = m_off;
  290. #else
  291. m_off = 1 + (t >> 2) + (*ip++ << 2);
  292. #endif
  293. NEED_OP(2);
  294. t = 2; COPY_DICT(t,m_off)
  295. #else /* !COPY_DICT */
  296. #if defined(LZO1Z)
  297. t = 1 + (t << 6) + (*ip++ >> 2);
  298. m_pos = op - t;
  299. last_m_off = t;
  300. #else
  301. m_pos = op - 1;
  302. m_pos -= t >> 2;
  303. m_pos -= *ip++ << 2;
  304. #endif
  305. TEST_LB(m_pos); NEED_OP(2);
  306. *op++ = *m_pos++;
  307. *op++ = *m_pos;
  308. #endif /* COPY_DICT */
  309. goto match_done;
  310. }
  311. /* copy match */
  312. #if defined(COPY_DICT)
  313. NEED_OP(t+3-1);
  314. t += 3-1; COPY_DICT(t,m_off)
  315. #else /* !COPY_DICT */
  316. TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
  317. #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
  318. # if !defined(LZO_UNALIGNED_OK_4)
  319. if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) {
  320. assert((op - m_pos) >= 4); /* both pointers are aligned */
  321. # else
  322. if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
  323. # endif
  324. COPY4(op,m_pos);
  325. op += 4; m_pos += 4; t -= 4 - (3 - 1);
  326. do {
  327. COPY4(op,m_pos);
  328. op += 4; m_pos += 4; t -= 4;
  329. } while (t >= 4);
  330. if (t > 0)
  331. do *op++ = *m_pos++; while (--t > 0);
  332. }
  333. else
  334. #endif
  335. {
  336. copy_match:
  337. *op++ = *m_pos++; *op++ = *m_pos++;
  338. do *op++ = *m_pos++; while (--t > 0);
  339. }
  340. #endif /* COPY_DICT */
  341. match_done:
  342. #if defined(LZO1Z)
  343. t = ip[-1] & 3;
  344. #else
  345. t = ip[-2] & 3;
  346. #endif
  347. if (t == 0)
  348. break;
  349. /* copy literals */
  350. match_next:
  351. assert(t > 0);
  352. assert(t < 4);
  353. NEED_OP(t);
  354. NEED_IP(t+1);
  355. #if 0
  356. do *op++ = *ip++; while (--t > 0);
  357. #else
  358. *op++ = *ip++;
  359. if (t > 1) {
  360. *op++ = *ip++;
  361. if (t > 2)
  362. *op++ = *ip++;
  363. }
  364. #endif
  365. t = *ip++;
  366. } while (TEST_IP && TEST_OP);
  367. }
  368. //#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
  369. /* no EOF code was found */
  370. *out_len = pd(op, out);
  371. return LZO_E_EOF_NOT_FOUND;
  372. //#endif
  373. eof_found:
  374. assert(t == 1);
  375. *out_len = pd(op, out);
  376. return (ip == ip_end ? LZO_E_OK :
  377. (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
  378. //#if defined(HAVE_NEED_IP)
  379. input_overrun:
  380. *out_len = pd(op, out);
  381. return LZO_E_INPUT_OVERRUN;
  382. //#endif
  383. //#if defined(HAVE_NEED_OP)
  384. output_overrun:
  385. *out_len = pd(op, out);
  386. return LZO_E_OUTPUT_OVERRUN;
  387. //#endif
  388. //#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
  389. lookbehind_overrun:
  390. *out_len = pd(op, out);
  391. return LZO_E_LOOKBEHIND_OVERRUN;
  392. //#endif
  393. }