10f66f451Sopenharmony_ci/* 20f66f451Sopenharmony_ci * Simple XZ decoder command line tool 30f66f451Sopenharmony_ci * 40f66f451Sopenharmony_ci * Author: Lasse Collin <lasse.collin@tukaani.org> 50f66f451Sopenharmony_ci * 60f66f451Sopenharmony_ci * This file has been put into the public domain. 70f66f451Sopenharmony_ci * You can do whatever you want with this file. 80f66f451Sopenharmony_ci * Modified for toybox by Isaac Dunham 90f66f451Sopenharmony_ciUSE_XZCAT(NEWTOY(xzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN)) 100f66f451Sopenharmony_ci 110f66f451Sopenharmony_ciconfig XZCAT 120f66f451Sopenharmony_ci bool "xzcat" 130f66f451Sopenharmony_ci default n 140f66f451Sopenharmony_ci help 150f66f451Sopenharmony_ci usage: xzcat [filename...] 160f66f451Sopenharmony_ci 170f66f451Sopenharmony_ci Decompress listed files to stdout. Use stdin if no files listed. 180f66f451Sopenharmony_ci 190f66f451Sopenharmony_ci*/ 200f66f451Sopenharmony_ci#define FOR_xzcat 210f66f451Sopenharmony_ci#include "toys.h" 220f66f451Sopenharmony_ci 230f66f451Sopenharmony_ci// BEGIN xz.h 240f66f451Sopenharmony_ci 250f66f451Sopenharmony_ci/** 260f66f451Sopenharmony_ci * enum xz_ret - Return codes 270f66f451Sopenharmony_ci * @XZ_OK: Everything is OK so far. More input or more 280f66f451Sopenharmony_ci * output space is required to continue. 290f66f451Sopenharmony_ci * @XZ_STREAM_END: Operation finished successfully. 300f66f451Sopenharmony_ci * @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding 310f66f451Sopenharmony_ci * is still possible in multi-call mode by simply 320f66f451Sopenharmony_ci * calling xz_dec_run() again. 330f66f451Sopenharmony_ci * Note that this return value is used only if 340f66f451Sopenharmony_ci * XZ_DEC_ANY_CHECK was defined at build time, 350f66f451Sopenharmony_ci * which is not used in the kernel. Unsupported 360f66f451Sopenharmony_ci * check types return XZ_OPTIONS_ERROR if 370f66f451Sopenharmony_ci * XZ_DEC_ANY_CHECK was not defined at build time. 380f66f451Sopenharmony_ci * @XZ_MEM_ERROR: Allocating memory failed. The amount of memory 390f66f451Sopenharmony_ci * that was tried to be allocated was no more than the 400f66f451Sopenharmony_ci * dict_max argument given to xz_dec_init(). 410f66f451Sopenharmony_ci * @XZ_MEMLIMIT_ERROR: A bigger LZMA2 dictionary would be needed than 420f66f451Sopenharmony_ci * allowed by the dict_max argument given to 430f66f451Sopenharmony_ci * xz_dec_init(). 440f66f451Sopenharmony_ci * @XZ_FORMAT_ERROR: File format was not recognized (wrong magic 450f66f451Sopenharmony_ci * bytes). 460f66f451Sopenharmony_ci * @XZ_OPTIONS_ERROR: This implementation doesn't support the requested 470f66f451Sopenharmony_ci * compression options. In the decoder this means 480f66f451Sopenharmony_ci * that the header CRC32 matches, but the header 490f66f451Sopenharmony_ci * itself specifies something that we don't support. 500f66f451Sopenharmony_ci * @XZ_DATA_ERROR: Compressed data is corrupt. 510f66f451Sopenharmony_ci * @XZ_BUF_ERROR: Cannot make any progress. Details are slightly 520f66f451Sopenharmony_ci * different between multi-call and single-call 530f66f451Sopenharmony_ci * mode; more information below. 540f66f451Sopenharmony_ci * 550f66f451Sopenharmony_ci * XZ_BUF_ERROR is returned when two consecutive calls to XZ code cannot 560f66f451Sopenharmony_ci * consume any input and cannot produce any new output. This happens when 570f66f451Sopenharmony_ci * there is no new input available, or the output buffer is full while at 580f66f451Sopenharmony_ci * least one output byte is still pending. Assuming your code is not buggy, 590f66f451Sopenharmony_ci * you can get this error only when decoding a compressed stream that is 600f66f451Sopenharmony_ci * truncated or otherwise corrupt. 610f66f451Sopenharmony_ci */ 620f66f451Sopenharmony_cienum xz_ret { 630f66f451Sopenharmony_ci XZ_OK, 640f66f451Sopenharmony_ci XZ_STREAM_END, 650f66f451Sopenharmony_ci XZ_UNSUPPORTED_CHECK, 660f66f451Sopenharmony_ci XZ_MEM_ERROR, 670f66f451Sopenharmony_ci XZ_MEMLIMIT_ERROR, 680f66f451Sopenharmony_ci XZ_FORMAT_ERROR, 690f66f451Sopenharmony_ci XZ_OPTIONS_ERROR, 700f66f451Sopenharmony_ci XZ_DATA_ERROR, 710f66f451Sopenharmony_ci XZ_BUF_ERROR 720f66f451Sopenharmony_ci}; 730f66f451Sopenharmony_ci 740f66f451Sopenharmony_ci/** 750f66f451Sopenharmony_ci * struct xz_buf - Passing input and output buffers to XZ code 760f66f451Sopenharmony_ci * @in: Beginning of the input buffer. This may be NULL if and only 770f66f451Sopenharmony_ci * if in_pos is equal to in_size. 780f66f451Sopenharmony_ci * @in_pos: Current position in the input buffer. This must not exceed 790f66f451Sopenharmony_ci * in_size. 800f66f451Sopenharmony_ci * @in_size: Size of the input buffer 810f66f451Sopenharmony_ci * @out: Beginning of the output buffer. This may be NULL if and only 820f66f451Sopenharmony_ci * if out_pos is equal to out_size. 830f66f451Sopenharmony_ci * @out_pos: Current position in the output buffer. This must not exceed 840f66f451Sopenharmony_ci * out_size. 850f66f451Sopenharmony_ci * @out_size: Size of the output buffer 860f66f451Sopenharmony_ci * 870f66f451Sopenharmony_ci * Only the contents of the output buffer from out[out_pos] onward, and 880f66f451Sopenharmony_ci * the variables in_pos and out_pos are modified by the XZ code. 890f66f451Sopenharmony_ci */ 900f66f451Sopenharmony_cistruct xz_buf { 910f66f451Sopenharmony_ci const uint8_t *in; 920f66f451Sopenharmony_ci size_t in_pos; 930f66f451Sopenharmony_ci size_t in_size; 940f66f451Sopenharmony_ci 950f66f451Sopenharmony_ci uint8_t *out; 960f66f451Sopenharmony_ci size_t out_pos; 970f66f451Sopenharmony_ci size_t out_size; 980f66f451Sopenharmony_ci}; 990f66f451Sopenharmony_ci 1000f66f451Sopenharmony_ci/** 1010f66f451Sopenharmony_ci * struct xz_dec - Opaque type to hold the XZ decoder state 1020f66f451Sopenharmony_ci */ 1030f66f451Sopenharmony_cistruct xz_dec; 1040f66f451Sopenharmony_ci 1050f66f451Sopenharmony_ci/** 1060f66f451Sopenharmony_ci * xz_dec_init() - Allocate and initialize a XZ decoder state 1070f66f451Sopenharmony_ci * @mode: Operation mode 1080f66f451Sopenharmony_ci * @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for 1090f66f451Sopenharmony_ci * multi-call decoding. LZMA2 dictionary is always 2^n bytes 1100f66f451Sopenharmony_ci * or 2^n + 2^(n-1) bytes (the latter sizes are less common 1110f66f451Sopenharmony_ci * in practice), so other values for dict_max don't make sense. 1120f66f451Sopenharmony_ci * In the kernel, dictionary sizes of 64 KiB, 128 KiB, 256 KiB, 1130f66f451Sopenharmony_ci * 512 KiB, and 1 MiB are probably the only reasonable values, 1140f66f451Sopenharmony_ci * except for kernel and initramfs images where a bigger 1150f66f451Sopenharmony_ci * dictionary can be fine and useful. 1160f66f451Sopenharmony_ci * 1170f66f451Sopenharmony_ci * dict_max specifies the maximum allowed dictionary size that xz_dec_run() 1180f66f451Sopenharmony_ci * may allocate once it has parsed the dictionary size from the stream 1190f66f451Sopenharmony_ci * headers. This way excessive allocations can be avoided while still 1200f66f451Sopenharmony_ci * limiting the maximum memory usage to a sane value to prevent running the 1210f66f451Sopenharmony_ci * system out of memory when decompressing streams from untrusted sources. 1220f66f451Sopenharmony_ci * 1230f66f451Sopenharmony_ci * On success, xz_dec_init() returns a pointer to struct xz_dec, which is 1240f66f451Sopenharmony_ci * ready to be used with xz_dec_run(). If memory allocation fails, 1250f66f451Sopenharmony_ci * xz_dec_init() returns NULL. 1260f66f451Sopenharmony_ci */ 1270f66f451Sopenharmony_cistruct xz_dec *xz_dec_init(uint32_t dict_max); 1280f66f451Sopenharmony_ci 1290f66f451Sopenharmony_ci/** 1300f66f451Sopenharmony_ci * xz_dec_run() - Run the XZ decoder 1310f66f451Sopenharmony_ci * @s: Decoder state allocated using xz_dec_init() 1320f66f451Sopenharmony_ci * @b: Input and output buffers 1330f66f451Sopenharmony_ci * 1340f66f451Sopenharmony_ci * The possible return values depend on build options and operation mode. 1350f66f451Sopenharmony_ci * See enum xz_ret for details. 1360f66f451Sopenharmony_ci * 1370f66f451Sopenharmony_ci * Note that if an error occurs in single-call mode (return value is not 1380f66f451Sopenharmony_ci * XZ_STREAM_END), b->in_pos and b->out_pos are not modified and the 1390f66f451Sopenharmony_ci * contents of the output buffer from b->out[b->out_pos] onward are 1400f66f451Sopenharmony_ci * undefined. This is true even after XZ_BUF_ERROR, because with some filter 1410f66f451Sopenharmony_ci * chains, there may be a second pass over the output buffer, and this pass 1420f66f451Sopenharmony_ci * cannot be properly done if the output buffer is truncated. Thus, you 1430f66f451Sopenharmony_ci * cannot give the single-call decoder a too small buffer and then expect to 1440f66f451Sopenharmony_ci * get that amount valid data from the beginning of the stream. You must use 1450f66f451Sopenharmony_ci * the multi-call decoder if you don't want to uncompress the whole stream. 1460f66f451Sopenharmony_ci */ 1470f66f451Sopenharmony_cienum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b); 1480f66f451Sopenharmony_ci 1490f66f451Sopenharmony_ci/** 1500f66f451Sopenharmony_ci * xz_dec_reset() - Reset an already allocated decoder state 1510f66f451Sopenharmony_ci * @s: Decoder state allocated using xz_dec_init() 1520f66f451Sopenharmony_ci * 1530f66f451Sopenharmony_ci * This function can be used to reset the multi-call decoder state without 1540f66f451Sopenharmony_ci * freeing and reallocating memory with xz_dec_end() and xz_dec_init(). 1550f66f451Sopenharmony_ci * 1560f66f451Sopenharmony_ci * In single-call mode, xz_dec_reset() is always called in the beginning of 1570f66f451Sopenharmony_ci * xz_dec_run(). Thus, explicit call to xz_dec_reset() is useful only in 1580f66f451Sopenharmony_ci * multi-call mode. 1590f66f451Sopenharmony_ci */ 1600f66f451Sopenharmony_civoid xz_dec_reset(struct xz_dec *s); 1610f66f451Sopenharmony_ci 1620f66f451Sopenharmony_ci/** 1630f66f451Sopenharmony_ci * xz_dec_end() - Free the memory allocated for the decoder state 1640f66f451Sopenharmony_ci * @s: Decoder state allocated using xz_dec_init(). If s is NULL, 1650f66f451Sopenharmony_ci * this function does nothing. 1660f66f451Sopenharmony_ci */ 1670f66f451Sopenharmony_civoid xz_dec_end(struct xz_dec *s); 1680f66f451Sopenharmony_ci 1690f66f451Sopenharmony_ci/* 1700f66f451Sopenharmony_ci * Update CRC32 value using the polynomial from IEEE-802.3. To start a new 1710f66f451Sopenharmony_ci * calculation, the third argument must be zero. To continue the calculation, 1720f66f451Sopenharmony_ci * the previously returned value is passed as the third argument. 1730f66f451Sopenharmony_ci */ 1740f66f451Sopenharmony_cistatic uint32_t xz_crc32_table[256]; 1750f66f451Sopenharmony_ci 1760f66f451Sopenharmony_ciuint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) 1770f66f451Sopenharmony_ci{ 1780f66f451Sopenharmony_ci crc = ~crc; 1790f66f451Sopenharmony_ci 1800f66f451Sopenharmony_ci while (size != 0) { 1810f66f451Sopenharmony_ci crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8); 1820f66f451Sopenharmony_ci --size; 1830f66f451Sopenharmony_ci } 1840f66f451Sopenharmony_ci 1850f66f451Sopenharmony_ci return ~crc; 1860f66f451Sopenharmony_ci} 1870f66f451Sopenharmony_ci 1880f66f451Sopenharmony_cistatic uint64_t xz_crc64_table[256]; 1890f66f451Sopenharmony_ci 1900f66f451Sopenharmony_ci 1910f66f451Sopenharmony_ci// END xz.h 1920f66f451Sopenharmony_ci 1930f66f451Sopenharmony_cistatic uint8_t in[BUFSIZ]; 1940f66f451Sopenharmony_cistatic uint8_t out[BUFSIZ]; 1950f66f451Sopenharmony_ci 1960f66f451Sopenharmony_civoid do_xzcat(int fd, char *name) 1970f66f451Sopenharmony_ci{ 1980f66f451Sopenharmony_ci struct xz_buf b; 1990f66f451Sopenharmony_ci struct xz_dec *s; 2000f66f451Sopenharmony_ci enum xz_ret ret; 2010f66f451Sopenharmony_ci const char *msg; 2020f66f451Sopenharmony_ci 2030f66f451Sopenharmony_ci crc_init(xz_crc32_table, 1); 2040f66f451Sopenharmony_ci const uint64_t poly = 0xC96C5795D7870F42ULL; 2050f66f451Sopenharmony_ci uint32_t i; 2060f66f451Sopenharmony_ci uint32_t j; 2070f66f451Sopenharmony_ci uint64_t r; 2080f66f451Sopenharmony_ci 2090f66f451Sopenharmony_ci /* initialize CRC64 table*/ 2100f66f451Sopenharmony_ci for (i = 0; i < 256; ++i) { 2110f66f451Sopenharmony_ci r = i; 2120f66f451Sopenharmony_ci for (j = 0; j < 8; ++j) 2130f66f451Sopenharmony_ci r = (r >> 1) ^ (poly & ~((r & 1) - 1)); 2140f66f451Sopenharmony_ci 2150f66f451Sopenharmony_ci xz_crc64_table[i] = r; 2160f66f451Sopenharmony_ci } 2170f66f451Sopenharmony_ci 2180f66f451Sopenharmony_ci /* 2190f66f451Sopenharmony_ci * Support up to 64 MiB dictionary. The actually needed memory 2200f66f451Sopenharmony_ci * is allocated once the headers have been parsed. 2210f66f451Sopenharmony_ci */ 2220f66f451Sopenharmony_ci s = xz_dec_init(1 << 26); 2230f66f451Sopenharmony_ci if (s == NULL) { 2240f66f451Sopenharmony_ci msg = "Memory allocation failed\n"; 2250f66f451Sopenharmony_ci goto error; 2260f66f451Sopenharmony_ci } 2270f66f451Sopenharmony_ci 2280f66f451Sopenharmony_ci b.in = in; 2290f66f451Sopenharmony_ci b.in_pos = 0; 2300f66f451Sopenharmony_ci b.in_size = 0; 2310f66f451Sopenharmony_ci b.out = out; 2320f66f451Sopenharmony_ci b.out_pos = 0; 2330f66f451Sopenharmony_ci b.out_size = BUFSIZ; 2340f66f451Sopenharmony_ci 2350f66f451Sopenharmony_ci for (;;) { 2360f66f451Sopenharmony_ci if (b.in_pos == b.in_size) { 2370f66f451Sopenharmony_ci b.in_size = read(fd, in, sizeof(in)); 2380f66f451Sopenharmony_ci b.in_pos = 0; 2390f66f451Sopenharmony_ci } 2400f66f451Sopenharmony_ci 2410f66f451Sopenharmony_ci ret = xz_dec_run(s, &b); 2420f66f451Sopenharmony_ci 2430f66f451Sopenharmony_ci if (b.out_pos == sizeof(out)) { 2440f66f451Sopenharmony_ci if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos) { 2450f66f451Sopenharmony_ci msg = "Write error\n"; 2460f66f451Sopenharmony_ci goto error; 2470f66f451Sopenharmony_ci } 2480f66f451Sopenharmony_ci 2490f66f451Sopenharmony_ci b.out_pos = 0; 2500f66f451Sopenharmony_ci } 2510f66f451Sopenharmony_ci 2520f66f451Sopenharmony_ci if (ret == XZ_OK) 2530f66f451Sopenharmony_ci continue; 2540f66f451Sopenharmony_ci 2550f66f451Sopenharmony_ci if (ret == XZ_UNSUPPORTED_CHECK) 2560f66f451Sopenharmony_ci continue; 2570f66f451Sopenharmony_ci 2580f66f451Sopenharmony_ci if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos) { 2590f66f451Sopenharmony_ci msg = "Write error\n"; 2600f66f451Sopenharmony_ci goto error; 2610f66f451Sopenharmony_ci } 2620f66f451Sopenharmony_ci 2630f66f451Sopenharmony_ci switch (ret) { 2640f66f451Sopenharmony_ci case XZ_STREAM_END: 2650f66f451Sopenharmony_ci xz_dec_end(s); 2660f66f451Sopenharmony_ci return; 2670f66f451Sopenharmony_ci 2680f66f451Sopenharmony_ci case XZ_MEM_ERROR: 2690f66f451Sopenharmony_ci msg = "Memory allocation failed\n"; 2700f66f451Sopenharmony_ci goto error; 2710f66f451Sopenharmony_ci 2720f66f451Sopenharmony_ci case XZ_MEMLIMIT_ERROR: 2730f66f451Sopenharmony_ci msg = "Memory usage limit reached\n"; 2740f66f451Sopenharmony_ci goto error; 2750f66f451Sopenharmony_ci 2760f66f451Sopenharmony_ci case XZ_FORMAT_ERROR: 2770f66f451Sopenharmony_ci msg = "Not a .xz file\n"; 2780f66f451Sopenharmony_ci goto error; 2790f66f451Sopenharmony_ci 2800f66f451Sopenharmony_ci case XZ_OPTIONS_ERROR: 2810f66f451Sopenharmony_ci msg = "Unsupported options in the .xz headers\n"; 2820f66f451Sopenharmony_ci goto error; 2830f66f451Sopenharmony_ci 2840f66f451Sopenharmony_ci case XZ_DATA_ERROR: 2850f66f451Sopenharmony_ci case XZ_BUF_ERROR: 2860f66f451Sopenharmony_ci msg = "File is corrupt\n"; 2870f66f451Sopenharmony_ci goto error; 2880f66f451Sopenharmony_ci 2890f66f451Sopenharmony_ci default: 2900f66f451Sopenharmony_ci msg = "Bug!\n"; 2910f66f451Sopenharmony_ci goto error; 2920f66f451Sopenharmony_ci } 2930f66f451Sopenharmony_ci } 2940f66f451Sopenharmony_ci 2950f66f451Sopenharmony_cierror: 2960f66f451Sopenharmony_ci xz_dec_end(s); 2970f66f451Sopenharmony_ci error_exit("%s", msg); 2980f66f451Sopenharmony_ci} 2990f66f451Sopenharmony_ci 3000f66f451Sopenharmony_civoid xzcat_main(void) 3010f66f451Sopenharmony_ci{ 3020f66f451Sopenharmony_ci loopfiles(toys.optargs, do_xzcat); 3030f66f451Sopenharmony_ci} 3040f66f451Sopenharmony_ci 3050f66f451Sopenharmony_ci// BEGIN xz_private.h 3060f66f451Sopenharmony_ci 3070f66f451Sopenharmony_ci 3080f66f451Sopenharmony_ci/* Uncomment as needed to enable BCJ filter decoders. 3090f66f451Sopenharmony_ci * These cost about 2.5 k when all are enabled; SPARC and IA64 make 0.7 k 3100f66f451Sopenharmony_ci * */ 3110f66f451Sopenharmony_ci 3120f66f451Sopenharmony_ci#define XZ_DEC_X86 3130f66f451Sopenharmony_ci#define XZ_DEC_POWERPC 3140f66f451Sopenharmony_ci#define XZ_DEC_IA64 3150f66f451Sopenharmony_ci#define XZ_DEC_ARM 3160f66f451Sopenharmony_ci#define XZ_DEC_ARMTHUMB 3170f66f451Sopenharmony_ci#define XZ_DEC_SPARC 3180f66f451Sopenharmony_ci 3190f66f451Sopenharmony_ci 3200f66f451Sopenharmony_ci#define memeq(a, b, size) (memcmp(a, b, size) == 0) 3210f66f451Sopenharmony_ci 3220f66f451Sopenharmony_ci/* Inline functions to access unaligned unsigned 32-bit integers */ 3230f66f451Sopenharmony_ci#ifndef get_unaligned_le32 3240f66f451Sopenharmony_cistatic inline uint32_t get_unaligned_le32(const uint8_t *buf) 3250f66f451Sopenharmony_ci{ 3260f66f451Sopenharmony_ci return (uint32_t)buf[0] 3270f66f451Sopenharmony_ci | ((uint32_t)buf[1] << 8) 3280f66f451Sopenharmony_ci | ((uint32_t)buf[2] << 16) 3290f66f451Sopenharmony_ci | ((uint32_t)buf[3] << 24); 3300f66f451Sopenharmony_ci} 3310f66f451Sopenharmony_ci#endif 3320f66f451Sopenharmony_ci 3330f66f451Sopenharmony_ci#ifndef get_unaligned_be32 3340f66f451Sopenharmony_cistatic inline uint32_t get_unaligned_be32(const uint8_t *buf) 3350f66f451Sopenharmony_ci{ 3360f66f451Sopenharmony_ci return (uint32_t)(buf[0] << 24) 3370f66f451Sopenharmony_ci | ((uint32_t)buf[1] << 16) 3380f66f451Sopenharmony_ci | ((uint32_t)buf[2] << 8) 3390f66f451Sopenharmony_ci | (uint32_t)buf[3]; 3400f66f451Sopenharmony_ci} 3410f66f451Sopenharmony_ci#endif 3420f66f451Sopenharmony_ci 3430f66f451Sopenharmony_ci#ifndef put_unaligned_le32 3440f66f451Sopenharmony_cistatic inline void put_unaligned_le32(uint32_t val, uint8_t *buf) 3450f66f451Sopenharmony_ci{ 3460f66f451Sopenharmony_ci buf[0] = (uint8_t)val; 3470f66f451Sopenharmony_ci buf[1] = (uint8_t)(val >> 8); 3480f66f451Sopenharmony_ci buf[2] = (uint8_t)(val >> 16); 3490f66f451Sopenharmony_ci buf[3] = (uint8_t)(val >> 24); 3500f66f451Sopenharmony_ci} 3510f66f451Sopenharmony_ci#endif 3520f66f451Sopenharmony_ci 3530f66f451Sopenharmony_ci#ifndef put_unaligned_be32 3540f66f451Sopenharmony_cistatic inline void put_unaligned_be32(uint32_t val, uint8_t *buf) 3550f66f451Sopenharmony_ci{ 3560f66f451Sopenharmony_ci buf[0] = (uint8_t)(val >> 24); 3570f66f451Sopenharmony_ci buf[1] = (uint8_t)(val >> 16); 3580f66f451Sopenharmony_ci buf[2] = (uint8_t)(val >> 8); 3590f66f451Sopenharmony_ci buf[3] = (uint8_t)val; 3600f66f451Sopenharmony_ci} 3610f66f451Sopenharmony_ci#endif 3620f66f451Sopenharmony_ci 3630f66f451Sopenharmony_ci/* 3640f66f451Sopenharmony_ci * Use get_unaligned_le32() also for aligned access for simplicity. On 3650f66f451Sopenharmony_ci * little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr)) 3660f66f451Sopenharmony_ci * could save a few bytes in code size. 3670f66f451Sopenharmony_ci */ 3680f66f451Sopenharmony_ci#ifndef get_le32 3690f66f451Sopenharmony_ci# define get_le32 get_unaligned_le32 3700f66f451Sopenharmony_ci#endif 3710f66f451Sopenharmony_ci 3720f66f451Sopenharmony_ci/* 3730f66f451Sopenharmony_ci * If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ. 3740f66f451Sopenharmony_ci * XZ_DEC_BCJ is used to enable generic support for BCJ decoders. 3750f66f451Sopenharmony_ci */ 3760f66f451Sopenharmony_ci#ifndef XZ_DEC_BCJ 3770f66f451Sopenharmony_ci# if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) \ 3780f66f451Sopenharmony_ci || defined(XZ_DEC_IA64) || defined(XZ_DEC_ARM) \ 3790f66f451Sopenharmony_ci || defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \ 3800f66f451Sopenharmony_ci || defined(XZ_DEC_SPARC) 3810f66f451Sopenharmony_ci# define XZ_DEC_BCJ 3820f66f451Sopenharmony_ci# endif 3830f66f451Sopenharmony_ci#endif 3840f66f451Sopenharmony_ci 3850f66f451Sopenharmony_ci/* 3860f66f451Sopenharmony_ci * Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used 3870f66f451Sopenharmony_ci * before calling xz_dec_lzma2_run(). 3880f66f451Sopenharmony_ci */ 3890f66f451Sopenharmony_cistruct xz_dec_lzma2 *xz_dec_lzma2_create(uint32_t dict_max); 3900f66f451Sopenharmony_ci 3910f66f451Sopenharmony_ci/* 3920f66f451Sopenharmony_ci * Decode the LZMA2 properties (one byte) and reset the decoder. Return 3930f66f451Sopenharmony_ci * XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not 3940f66f451Sopenharmony_ci * big enough, and XZ_OPTIONS_ERROR if props indicates something that this 3950f66f451Sopenharmony_ci * decoder doesn't support. 3960f66f451Sopenharmony_ci */ 3970f66f451Sopenharmony_cienum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, 3980f66f451Sopenharmony_ci uint8_t props); 3990f66f451Sopenharmony_ci 4000f66f451Sopenharmony_ci/* Decode raw LZMA2 stream from b->in to b->out. */ 4010f66f451Sopenharmony_cienum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, 4020f66f451Sopenharmony_ci struct xz_buf *b); 4030f66f451Sopenharmony_ci 4040f66f451Sopenharmony_ci// END "xz_private.h" 4050f66f451Sopenharmony_ci 4060f66f451Sopenharmony_ci 4070f66f451Sopenharmony_ci 4080f66f451Sopenharmony_ci 4090f66f451Sopenharmony_ci/* 4100f66f451Sopenharmony_ci * Branch/Call/Jump (BCJ) filter decoders 4110f66f451Sopenharmony_ci * The rest of the code is inside this ifdef. It makes things a little more 4120f66f451Sopenharmony_ci * convenient when building without support for any BCJ filters. 4130f66f451Sopenharmony_ci */ 4140f66f451Sopenharmony_ci#ifdef XZ_DEC_BCJ 4150f66f451Sopenharmony_ci 4160f66f451Sopenharmony_cistruct xz_dec_bcj { 4170f66f451Sopenharmony_ci /* Type of the BCJ filter being used */ 4180f66f451Sopenharmony_ci enum { 4190f66f451Sopenharmony_ci BCJ_X86 = 4, /* x86 or x86-64 */ 4200f66f451Sopenharmony_ci BCJ_POWERPC = 5, /* Big endian only */ 4210f66f451Sopenharmony_ci BCJ_IA64 = 6, /* Big or little endian */ 4220f66f451Sopenharmony_ci BCJ_ARM = 7, /* Little endian only */ 4230f66f451Sopenharmony_ci BCJ_ARMTHUMB = 8, /* Little endian only */ 4240f66f451Sopenharmony_ci BCJ_SPARC = 9 /* Big or little endian */ 4250f66f451Sopenharmony_ci } type; 4260f66f451Sopenharmony_ci 4270f66f451Sopenharmony_ci /* 4280f66f451Sopenharmony_ci * Return value of the next filter in the chain. We need to preserve 4290f66f451Sopenharmony_ci * this information across calls, because we must not call the next 4300f66f451Sopenharmony_ci * filter anymore once it has returned XZ_STREAM_END. 4310f66f451Sopenharmony_ci */ 4320f66f451Sopenharmony_ci enum xz_ret ret; 4330f66f451Sopenharmony_ci 4340f66f451Sopenharmony_ci /* 4350f66f451Sopenharmony_ci * Absolute position relative to the beginning of the uncompressed 4360f66f451Sopenharmony_ci * data (in a single .xz Block). We care only about the lowest 32 4370f66f451Sopenharmony_ci * bits so this doesn't need to be uint64_t even with big files. 4380f66f451Sopenharmony_ci */ 4390f66f451Sopenharmony_ci uint32_t pos; 4400f66f451Sopenharmony_ci 4410f66f451Sopenharmony_ci /* x86 filter state */ 4420f66f451Sopenharmony_ci uint32_t x86_prev_mask; 4430f66f451Sopenharmony_ci 4440f66f451Sopenharmony_ci /* Temporary space to hold the variables from struct xz_buf */ 4450f66f451Sopenharmony_ci uint8_t *out; 4460f66f451Sopenharmony_ci size_t out_pos; 4470f66f451Sopenharmony_ci size_t out_size; 4480f66f451Sopenharmony_ci 4490f66f451Sopenharmony_ci struct { 4500f66f451Sopenharmony_ci /* Amount of already filtered data in the beginning of buf */ 4510f66f451Sopenharmony_ci size_t filtered; 4520f66f451Sopenharmony_ci 4530f66f451Sopenharmony_ci /* Total amount of data currently stored in buf */ 4540f66f451Sopenharmony_ci size_t size; 4550f66f451Sopenharmony_ci 4560f66f451Sopenharmony_ci /* 4570f66f451Sopenharmony_ci * Buffer to hold a mix of filtered and unfiltered data. This 4580f66f451Sopenharmony_ci * needs to be big enough to hold Alignment + 2 * Look-ahead: 4590f66f451Sopenharmony_ci * 4600f66f451Sopenharmony_ci * Type Alignment Look-ahead 4610f66f451Sopenharmony_ci * x86 1 4 4620f66f451Sopenharmony_ci * PowerPC 4 0 4630f66f451Sopenharmony_ci * IA-64 16 0 4640f66f451Sopenharmony_ci * ARM 4 0 4650f66f451Sopenharmony_ci * ARM-Thumb 2 2 4660f66f451Sopenharmony_ci * SPARC 4 0 4670f66f451Sopenharmony_ci */ 4680f66f451Sopenharmony_ci uint8_t buf[16]; 4690f66f451Sopenharmony_ci } temp; 4700f66f451Sopenharmony_ci}; 4710f66f451Sopenharmony_ci 4720f66f451Sopenharmony_ci/* 4730f66f451Sopenharmony_ci * Decode the Filter ID of a BCJ filter. This implementation doesn't 4740f66f451Sopenharmony_ci * support custom start offsets, so no decoding of Filter Properties 4750f66f451Sopenharmony_ci * is needed. Returns XZ_OK if the given Filter ID is supported. 4760f66f451Sopenharmony_ci * Otherwise XZ_OPTIONS_ERROR is returned. 4770f66f451Sopenharmony_ci */ 4780f66f451Sopenharmony_cienum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id); 4790f66f451Sopenharmony_ci 4800f66f451Sopenharmony_ci/* 4810f66f451Sopenharmony_ci * Decode raw BCJ + LZMA2 stream. This must be used only if there actually is 4820f66f451Sopenharmony_ci * a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run() 4830f66f451Sopenharmony_ci * must be called directly. 4840f66f451Sopenharmony_ci */ 4850f66f451Sopenharmony_cienum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, 4860f66f451Sopenharmony_ci struct xz_dec_lzma2 *lzma2, 4870f66f451Sopenharmony_ci struct xz_buf *b); 4880f66f451Sopenharmony_ci 4890f66f451Sopenharmony_ci#ifdef XZ_DEC_X86 4900f66f451Sopenharmony_ci/* 4910f66f451Sopenharmony_ci * This is used to test the most significant byte of a memory address 4920f66f451Sopenharmony_ci * in an x86 instruction. 4930f66f451Sopenharmony_ci */ 4940f66f451Sopenharmony_cistatic inline int bcj_x86_test_msbyte(uint8_t b) 4950f66f451Sopenharmony_ci{ 4960f66f451Sopenharmony_ci return b == 0x00 || b == 0xFF; 4970f66f451Sopenharmony_ci} 4980f66f451Sopenharmony_ci 4990f66f451Sopenharmony_cistatic size_t bcj_x86(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 5000f66f451Sopenharmony_ci{ 5010f66f451Sopenharmony_ci static const int mask_to_allowed_status[8] 5020f66f451Sopenharmony_ci = { 1,1,1,0,1,0,0,0 }; 5030f66f451Sopenharmony_ci 5040f66f451Sopenharmony_ci static const uint8_t mask_to_bit_num[8] = { 0, 1, 2, 2, 3, 3, 3, 3 }; 5050f66f451Sopenharmony_ci 5060f66f451Sopenharmony_ci size_t i; 5070f66f451Sopenharmony_ci size_t prev_pos = (size_t)-1; 5080f66f451Sopenharmony_ci uint32_t prev_mask = s->x86_prev_mask; 5090f66f451Sopenharmony_ci uint32_t src; 5100f66f451Sopenharmony_ci uint32_t dest; 5110f66f451Sopenharmony_ci uint32_t j; 5120f66f451Sopenharmony_ci uint8_t b; 5130f66f451Sopenharmony_ci 5140f66f451Sopenharmony_ci if (size <= 4) 5150f66f451Sopenharmony_ci return 0; 5160f66f451Sopenharmony_ci 5170f66f451Sopenharmony_ci size -= 4; 5180f66f451Sopenharmony_ci for (i = 0; i < size; ++i) { 5190f66f451Sopenharmony_ci if ((buf[i] & 0xFE) != 0xE8) 5200f66f451Sopenharmony_ci continue; 5210f66f451Sopenharmony_ci 5220f66f451Sopenharmony_ci prev_pos = i - prev_pos; 5230f66f451Sopenharmony_ci if (prev_pos > 3) { 5240f66f451Sopenharmony_ci prev_mask = 0; 5250f66f451Sopenharmony_ci } else { 5260f66f451Sopenharmony_ci prev_mask = (prev_mask << (prev_pos - 1)) & 7; 5270f66f451Sopenharmony_ci if (prev_mask != 0) { 5280f66f451Sopenharmony_ci b = buf[i + 4 - mask_to_bit_num[prev_mask]]; 5290f66f451Sopenharmony_ci if (!mask_to_allowed_status[prev_mask] 5300f66f451Sopenharmony_ci || bcj_x86_test_msbyte(b)) { 5310f66f451Sopenharmony_ci prev_pos = i; 5320f66f451Sopenharmony_ci prev_mask = (prev_mask << 1) | 1; 5330f66f451Sopenharmony_ci continue; 5340f66f451Sopenharmony_ci } 5350f66f451Sopenharmony_ci } 5360f66f451Sopenharmony_ci } 5370f66f451Sopenharmony_ci 5380f66f451Sopenharmony_ci prev_pos = i; 5390f66f451Sopenharmony_ci 5400f66f451Sopenharmony_ci if (bcj_x86_test_msbyte(buf[i + 4])) { 5410f66f451Sopenharmony_ci src = get_unaligned_le32(buf + i + 1); 5420f66f451Sopenharmony_ci for (;;) { 5430f66f451Sopenharmony_ci dest = src - (s->pos + (uint32_t)i + 5); 5440f66f451Sopenharmony_ci if (prev_mask == 0) 5450f66f451Sopenharmony_ci break; 5460f66f451Sopenharmony_ci 5470f66f451Sopenharmony_ci j = mask_to_bit_num[prev_mask] * 8; 5480f66f451Sopenharmony_ci b = (uint8_t)(dest >> (24 - j)); 5490f66f451Sopenharmony_ci if (!bcj_x86_test_msbyte(b)) 5500f66f451Sopenharmony_ci break; 5510f66f451Sopenharmony_ci 5520f66f451Sopenharmony_ci src = dest ^ (((uint32_t)1 << (32 - j)) - 1); 5530f66f451Sopenharmony_ci } 5540f66f451Sopenharmony_ci 5550f66f451Sopenharmony_ci dest &= 0x01FFFFFF; 5560f66f451Sopenharmony_ci dest |= (uint32_t)0 - (dest & 0x01000000); 5570f66f451Sopenharmony_ci put_unaligned_le32(dest, buf + i + 1); 5580f66f451Sopenharmony_ci i += 4; 5590f66f451Sopenharmony_ci } else { 5600f66f451Sopenharmony_ci prev_mask = (prev_mask << 1) | 1; 5610f66f451Sopenharmony_ci } 5620f66f451Sopenharmony_ci } 5630f66f451Sopenharmony_ci 5640f66f451Sopenharmony_ci prev_pos = i - prev_pos; 5650f66f451Sopenharmony_ci s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1); 5660f66f451Sopenharmony_ci return i; 5670f66f451Sopenharmony_ci} 5680f66f451Sopenharmony_ci#endif 5690f66f451Sopenharmony_ci 5700f66f451Sopenharmony_ci#ifdef XZ_DEC_POWERPC 5710f66f451Sopenharmony_cistatic size_t bcj_powerpc(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 5720f66f451Sopenharmony_ci{ 5730f66f451Sopenharmony_ci size_t i; 5740f66f451Sopenharmony_ci uint32_t instr; 5750f66f451Sopenharmony_ci 5760f66f451Sopenharmony_ci for (i = 0; i + 4 <= size; i += 4) { 5770f66f451Sopenharmony_ci instr = get_unaligned_be32(buf + i); 5780f66f451Sopenharmony_ci if ((instr & 0xFC000003) == 0x48000001) { 5790f66f451Sopenharmony_ci instr &= 0x03FFFFFC; 5800f66f451Sopenharmony_ci instr -= s->pos + (uint32_t)i; 5810f66f451Sopenharmony_ci instr &= 0x03FFFFFC; 5820f66f451Sopenharmony_ci instr |= 0x48000001; 5830f66f451Sopenharmony_ci put_unaligned_be32(instr, buf + i); 5840f66f451Sopenharmony_ci } 5850f66f451Sopenharmony_ci } 5860f66f451Sopenharmony_ci 5870f66f451Sopenharmony_ci return i; 5880f66f451Sopenharmony_ci} 5890f66f451Sopenharmony_ci#endif 5900f66f451Sopenharmony_ci 5910f66f451Sopenharmony_ci#ifdef XZ_DEC_IA64 5920f66f451Sopenharmony_cistatic size_t bcj_ia64(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 5930f66f451Sopenharmony_ci{ 5940f66f451Sopenharmony_ci static const uint8_t branch_table[32] = { 5950f66f451Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 5960f66f451Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 5970f66f451Sopenharmony_ci 4, 4, 6, 6, 0, 0, 7, 7, 5980f66f451Sopenharmony_ci 4, 4, 0, 0, 4, 4, 0, 0 5990f66f451Sopenharmony_ci }; 6000f66f451Sopenharmony_ci 6010f66f451Sopenharmony_ci /* 6020f66f451Sopenharmony_ci * The local variables take a little bit stack space, but it's less 6030f66f451Sopenharmony_ci * than what LZMA2 decoder takes, so it doesn't make sense to reduce 6040f66f451Sopenharmony_ci * stack usage here without doing that for the LZMA2 decoder too. 6050f66f451Sopenharmony_ci */ 6060f66f451Sopenharmony_ci 6070f66f451Sopenharmony_ci /* Loop counters */ 6080f66f451Sopenharmony_ci size_t i; 6090f66f451Sopenharmony_ci size_t j; 6100f66f451Sopenharmony_ci 6110f66f451Sopenharmony_ci /* Instruction slot (0, 1, or 2) in the 128-bit instruction word */ 6120f66f451Sopenharmony_ci uint32_t slot; 6130f66f451Sopenharmony_ci 6140f66f451Sopenharmony_ci /* Bitwise offset of the instruction indicated by slot */ 6150f66f451Sopenharmony_ci uint32_t bit_pos; 6160f66f451Sopenharmony_ci 6170f66f451Sopenharmony_ci /* bit_pos split into byte and bit parts */ 6180f66f451Sopenharmony_ci uint32_t byte_pos; 6190f66f451Sopenharmony_ci uint32_t bit_res; 6200f66f451Sopenharmony_ci 6210f66f451Sopenharmony_ci /* Address part of an instruction */ 6220f66f451Sopenharmony_ci uint32_t addr; 6230f66f451Sopenharmony_ci 6240f66f451Sopenharmony_ci /* Mask used to detect which instructions to convert */ 6250f66f451Sopenharmony_ci uint32_t mask; 6260f66f451Sopenharmony_ci 6270f66f451Sopenharmony_ci /* 41-bit instruction stored somewhere in the lowest 48 bits */ 6280f66f451Sopenharmony_ci uint64_t instr; 6290f66f451Sopenharmony_ci 6300f66f451Sopenharmony_ci /* Instruction normalized with bit_res for easier manipulation */ 6310f66f451Sopenharmony_ci uint64_t norm; 6320f66f451Sopenharmony_ci 6330f66f451Sopenharmony_ci for (i = 0; i + 16 <= size; i += 16) { 6340f66f451Sopenharmony_ci mask = branch_table[buf[i] & 0x1F]; 6350f66f451Sopenharmony_ci for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) { 6360f66f451Sopenharmony_ci if (((mask >> slot) & 1) == 0) 6370f66f451Sopenharmony_ci continue; 6380f66f451Sopenharmony_ci 6390f66f451Sopenharmony_ci byte_pos = bit_pos >> 3; 6400f66f451Sopenharmony_ci bit_res = bit_pos & 7; 6410f66f451Sopenharmony_ci instr = 0; 6420f66f451Sopenharmony_ci for (j = 0; j < 6; ++j) 6430f66f451Sopenharmony_ci instr |= (uint64_t)(buf[i + j + byte_pos]) 6440f66f451Sopenharmony_ci << (8 * j); 6450f66f451Sopenharmony_ci 6460f66f451Sopenharmony_ci norm = instr >> bit_res; 6470f66f451Sopenharmony_ci 6480f66f451Sopenharmony_ci if (((norm >> 37) & 0x0F) == 0x05 6490f66f451Sopenharmony_ci && ((norm >> 9) & 0x07) == 0) { 6500f66f451Sopenharmony_ci addr = (norm >> 13) & 0x0FFFFF; 6510f66f451Sopenharmony_ci addr |= ((uint32_t)(norm >> 36) & 1) << 20; 6520f66f451Sopenharmony_ci addr <<= 4; 6530f66f451Sopenharmony_ci addr -= s->pos + (uint32_t)i; 6540f66f451Sopenharmony_ci addr >>= 4; 6550f66f451Sopenharmony_ci 6560f66f451Sopenharmony_ci norm &= ~((uint64_t)0x8FFFFF << 13); 6570f66f451Sopenharmony_ci norm |= (uint64_t)(addr & 0x0FFFFF) << 13; 6580f66f451Sopenharmony_ci norm |= (uint64_t)(addr & 0x100000) 6590f66f451Sopenharmony_ci << (36 - 20); 6600f66f451Sopenharmony_ci 6610f66f451Sopenharmony_ci instr &= (1 << bit_res) - 1; 6620f66f451Sopenharmony_ci instr |= norm << bit_res; 6630f66f451Sopenharmony_ci 6640f66f451Sopenharmony_ci for (j = 0; j < 6; j++) 6650f66f451Sopenharmony_ci buf[i + j + byte_pos] 6660f66f451Sopenharmony_ci = (uint8_t)(instr >> (8 * j)); 6670f66f451Sopenharmony_ci } 6680f66f451Sopenharmony_ci } 6690f66f451Sopenharmony_ci } 6700f66f451Sopenharmony_ci 6710f66f451Sopenharmony_ci return i; 6720f66f451Sopenharmony_ci} 6730f66f451Sopenharmony_ci#endif 6740f66f451Sopenharmony_ci 6750f66f451Sopenharmony_ci#ifdef XZ_DEC_ARM 6760f66f451Sopenharmony_cistatic size_t bcj_arm(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 6770f66f451Sopenharmony_ci{ 6780f66f451Sopenharmony_ci size_t i; 6790f66f451Sopenharmony_ci uint32_t addr; 6800f66f451Sopenharmony_ci 6810f66f451Sopenharmony_ci for (i = 0; i + 4 <= size; i += 4) { 6820f66f451Sopenharmony_ci if (buf[i + 3] == 0xEB) { 6830f66f451Sopenharmony_ci addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8) 6840f66f451Sopenharmony_ci | ((uint32_t)buf[i + 2] << 16); 6850f66f451Sopenharmony_ci addr <<= 2; 6860f66f451Sopenharmony_ci addr -= s->pos + (uint32_t)i + 8; 6870f66f451Sopenharmony_ci addr >>= 2; 6880f66f451Sopenharmony_ci buf[i] = (uint8_t)addr; 6890f66f451Sopenharmony_ci buf[i + 1] = (uint8_t)(addr >> 8); 6900f66f451Sopenharmony_ci buf[i + 2] = (uint8_t)(addr >> 16); 6910f66f451Sopenharmony_ci } 6920f66f451Sopenharmony_ci } 6930f66f451Sopenharmony_ci 6940f66f451Sopenharmony_ci return i; 6950f66f451Sopenharmony_ci} 6960f66f451Sopenharmony_ci#endif 6970f66f451Sopenharmony_ci 6980f66f451Sopenharmony_ci#ifdef XZ_DEC_ARMTHUMB 6990f66f451Sopenharmony_cistatic size_t bcj_armthumb(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 7000f66f451Sopenharmony_ci{ 7010f66f451Sopenharmony_ci size_t i; 7020f66f451Sopenharmony_ci uint32_t addr; 7030f66f451Sopenharmony_ci 7040f66f451Sopenharmony_ci for (i = 0; i + 4 <= size; i += 2) { 7050f66f451Sopenharmony_ci if ((buf[i + 1] & 0xF8) == 0xF0 7060f66f451Sopenharmony_ci && (buf[i + 3] & 0xF8) == 0xF8) { 7070f66f451Sopenharmony_ci addr = (((uint32_t)buf[i + 1] & 0x07) << 19) 7080f66f451Sopenharmony_ci | ((uint32_t)buf[i] << 11) 7090f66f451Sopenharmony_ci | (((uint32_t)buf[i + 3] & 0x07) << 8) 7100f66f451Sopenharmony_ci | (uint32_t)buf[i + 2]; 7110f66f451Sopenharmony_ci addr <<= 1; 7120f66f451Sopenharmony_ci addr -= s->pos + (uint32_t)i + 4; 7130f66f451Sopenharmony_ci addr >>= 1; 7140f66f451Sopenharmony_ci buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07)); 7150f66f451Sopenharmony_ci buf[i] = (uint8_t)(addr >> 11); 7160f66f451Sopenharmony_ci buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07)); 7170f66f451Sopenharmony_ci buf[i + 2] = (uint8_t)addr; 7180f66f451Sopenharmony_ci i += 2; 7190f66f451Sopenharmony_ci } 7200f66f451Sopenharmony_ci } 7210f66f451Sopenharmony_ci 7220f66f451Sopenharmony_ci return i; 7230f66f451Sopenharmony_ci} 7240f66f451Sopenharmony_ci#endif 7250f66f451Sopenharmony_ci 7260f66f451Sopenharmony_ci#ifdef XZ_DEC_SPARC 7270f66f451Sopenharmony_cistatic size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 7280f66f451Sopenharmony_ci{ 7290f66f451Sopenharmony_ci size_t i; 7300f66f451Sopenharmony_ci uint32_t instr; 7310f66f451Sopenharmony_ci 7320f66f451Sopenharmony_ci for (i = 0; i + 4 <= size; i += 4) { 7330f66f451Sopenharmony_ci instr = get_unaligned_be32(buf + i); 7340f66f451Sopenharmony_ci if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) { 7350f66f451Sopenharmony_ci instr <<= 2; 7360f66f451Sopenharmony_ci instr -= s->pos + (uint32_t)i; 7370f66f451Sopenharmony_ci instr >>= 2; 7380f66f451Sopenharmony_ci instr = ((uint32_t)0x40000000 - (instr & 0x400000)) 7390f66f451Sopenharmony_ci | 0x40000000 | (instr & 0x3FFFFF); 7400f66f451Sopenharmony_ci put_unaligned_be32(instr, buf + i); 7410f66f451Sopenharmony_ci } 7420f66f451Sopenharmony_ci } 7430f66f451Sopenharmony_ci 7440f66f451Sopenharmony_ci return i; 7450f66f451Sopenharmony_ci} 7460f66f451Sopenharmony_ci#endif 7470f66f451Sopenharmony_ci 7480f66f451Sopenharmony_ci/* 7490f66f451Sopenharmony_ci * Apply the selected BCJ filter. Update *pos and s->pos to match the amount 7500f66f451Sopenharmony_ci * of data that got filtered. 7510f66f451Sopenharmony_ci * 7520f66f451Sopenharmony_ci * NOTE: This is implemented as a switch statement to avoid using function 7530f66f451Sopenharmony_ci * pointers, which could be problematic in the kernel boot code, which must 7540f66f451Sopenharmony_ci * avoid pointers to static data (at least on x86). 7550f66f451Sopenharmony_ci */ 7560f66f451Sopenharmony_cistatic void bcj_apply(struct xz_dec_bcj *s, 7570f66f451Sopenharmony_ci uint8_t *buf, size_t *pos, size_t size) 7580f66f451Sopenharmony_ci{ 7590f66f451Sopenharmony_ci size_t filtered; 7600f66f451Sopenharmony_ci 7610f66f451Sopenharmony_ci buf += *pos; 7620f66f451Sopenharmony_ci size -= *pos; 7630f66f451Sopenharmony_ci 7640f66f451Sopenharmony_ci switch (s->type) { 7650f66f451Sopenharmony_ci#ifdef XZ_DEC_X86 7660f66f451Sopenharmony_ci case BCJ_X86: 7670f66f451Sopenharmony_ci filtered = bcj_x86(s, buf, size); 7680f66f451Sopenharmony_ci break; 7690f66f451Sopenharmony_ci#endif 7700f66f451Sopenharmony_ci#ifdef XZ_DEC_POWERPC 7710f66f451Sopenharmony_ci case BCJ_POWERPC: 7720f66f451Sopenharmony_ci filtered = bcj_powerpc(s, buf, size); 7730f66f451Sopenharmony_ci break; 7740f66f451Sopenharmony_ci#endif 7750f66f451Sopenharmony_ci#ifdef XZ_DEC_IA64 7760f66f451Sopenharmony_ci case BCJ_IA64: 7770f66f451Sopenharmony_ci filtered = bcj_ia64(s, buf, size); 7780f66f451Sopenharmony_ci break; 7790f66f451Sopenharmony_ci#endif 7800f66f451Sopenharmony_ci#ifdef XZ_DEC_ARM 7810f66f451Sopenharmony_ci case BCJ_ARM: 7820f66f451Sopenharmony_ci filtered = bcj_arm(s, buf, size); 7830f66f451Sopenharmony_ci break; 7840f66f451Sopenharmony_ci#endif 7850f66f451Sopenharmony_ci#ifdef XZ_DEC_ARMTHUMB 7860f66f451Sopenharmony_ci case BCJ_ARMTHUMB: 7870f66f451Sopenharmony_ci filtered = bcj_armthumb(s, buf, size); 7880f66f451Sopenharmony_ci break; 7890f66f451Sopenharmony_ci#endif 7900f66f451Sopenharmony_ci#ifdef XZ_DEC_SPARC 7910f66f451Sopenharmony_ci case BCJ_SPARC: 7920f66f451Sopenharmony_ci filtered = bcj_sparc(s, buf, size); 7930f66f451Sopenharmony_ci break; 7940f66f451Sopenharmony_ci#endif 7950f66f451Sopenharmony_ci default: 7960f66f451Sopenharmony_ci /* Never reached but silence compiler warnings. */ 7970f66f451Sopenharmony_ci filtered = 0; 7980f66f451Sopenharmony_ci break; 7990f66f451Sopenharmony_ci } 8000f66f451Sopenharmony_ci 8010f66f451Sopenharmony_ci *pos += filtered; 8020f66f451Sopenharmony_ci s->pos += filtered; 8030f66f451Sopenharmony_ci} 8040f66f451Sopenharmony_ci 8050f66f451Sopenharmony_ci/* 8060f66f451Sopenharmony_ci * Flush pending filtered data from temp to the output buffer. 8070f66f451Sopenharmony_ci * Move the remaining mixture of possibly filtered and unfiltered 8080f66f451Sopenharmony_ci * data to the beginning of temp. 8090f66f451Sopenharmony_ci */ 8100f66f451Sopenharmony_cistatic void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b) 8110f66f451Sopenharmony_ci{ 8120f66f451Sopenharmony_ci size_t copy_size; 8130f66f451Sopenharmony_ci 8140f66f451Sopenharmony_ci copy_size = minof(s->temp.filtered, b->out_size - b->out_pos); 8150f66f451Sopenharmony_ci memcpy(b->out + b->out_pos, s->temp.buf, copy_size); 8160f66f451Sopenharmony_ci b->out_pos += copy_size; 8170f66f451Sopenharmony_ci 8180f66f451Sopenharmony_ci s->temp.filtered -= copy_size; 8190f66f451Sopenharmony_ci s->temp.size -= copy_size; 8200f66f451Sopenharmony_ci memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size); 8210f66f451Sopenharmony_ci} 8220f66f451Sopenharmony_ci 8230f66f451Sopenharmony_ci/* 8240f66f451Sopenharmony_ci * The BCJ filter functions are primitive in sense that they process the 8250f66f451Sopenharmony_ci * data in chunks of 1-16 bytes. To hide this issue, this function does 8260f66f451Sopenharmony_ci * some buffering. 8270f66f451Sopenharmony_ci */ 8280f66f451Sopenharmony_cienum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, 8290f66f451Sopenharmony_ci struct xz_dec_lzma2 *lzma2, 8300f66f451Sopenharmony_ci struct xz_buf *b) 8310f66f451Sopenharmony_ci{ 8320f66f451Sopenharmony_ci size_t out_start; 8330f66f451Sopenharmony_ci 8340f66f451Sopenharmony_ci /* 8350f66f451Sopenharmony_ci * Flush pending already filtered data to the output buffer. Return 8360f66f451Sopenharmony_ci * immediatelly if we couldn't flush everything, or if the next 8370f66f451Sopenharmony_ci * filter in the chain had already returned XZ_STREAM_END. 8380f66f451Sopenharmony_ci */ 8390f66f451Sopenharmony_ci if (s->temp.filtered > 0) { 8400f66f451Sopenharmony_ci bcj_flush(s, b); 8410f66f451Sopenharmony_ci if (s->temp.filtered > 0) 8420f66f451Sopenharmony_ci return XZ_OK; 8430f66f451Sopenharmony_ci 8440f66f451Sopenharmony_ci if (s->ret == XZ_STREAM_END) 8450f66f451Sopenharmony_ci return XZ_STREAM_END; 8460f66f451Sopenharmony_ci } 8470f66f451Sopenharmony_ci 8480f66f451Sopenharmony_ci /* 8490f66f451Sopenharmony_ci * If we have more output space than what is currently pending in 8500f66f451Sopenharmony_ci * temp, copy the unfiltered data from temp to the output buffer 8510f66f451Sopenharmony_ci * and try to fill the output buffer by decoding more data from the 8520f66f451Sopenharmony_ci * next filter in the chain. Apply the BCJ filter on the new data 8530f66f451Sopenharmony_ci * in the output buffer. If everything cannot be filtered, copy it 8540f66f451Sopenharmony_ci * to temp and rewind the output buffer position accordingly. 8550f66f451Sopenharmony_ci * 8560f66f451Sopenharmony_ci * This needs to be always run when temp.size == 0 to handle a special 8570f66f451Sopenharmony_ci * case where the output buffer is full and the next filter has no 8580f66f451Sopenharmony_ci * more output coming but hasn't returned XZ_STREAM_END yet. 8590f66f451Sopenharmony_ci */ 8600f66f451Sopenharmony_ci if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) { 8610f66f451Sopenharmony_ci out_start = b->out_pos; 8620f66f451Sopenharmony_ci memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); 8630f66f451Sopenharmony_ci b->out_pos += s->temp.size; 8640f66f451Sopenharmony_ci 8650f66f451Sopenharmony_ci s->ret = xz_dec_lzma2_run(lzma2, b); 8660f66f451Sopenharmony_ci if (s->ret != XZ_STREAM_END 8670f66f451Sopenharmony_ci && (s->ret != XZ_OK )) 8680f66f451Sopenharmony_ci return s->ret; 8690f66f451Sopenharmony_ci 8700f66f451Sopenharmony_ci bcj_apply(s, b->out, &out_start, b->out_pos); 8710f66f451Sopenharmony_ci 8720f66f451Sopenharmony_ci /* 8730f66f451Sopenharmony_ci * As an exception, if the next filter returned XZ_STREAM_END, 8740f66f451Sopenharmony_ci * we can do that too, since the last few bytes that remain 8750f66f451Sopenharmony_ci * unfiltered are meant to remain unfiltered. 8760f66f451Sopenharmony_ci */ 8770f66f451Sopenharmony_ci if (s->ret == XZ_STREAM_END) 8780f66f451Sopenharmony_ci return XZ_STREAM_END; 8790f66f451Sopenharmony_ci 8800f66f451Sopenharmony_ci s->temp.size = b->out_pos - out_start; 8810f66f451Sopenharmony_ci b->out_pos -= s->temp.size; 8820f66f451Sopenharmony_ci memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); 8830f66f451Sopenharmony_ci 8840f66f451Sopenharmony_ci /* 8850f66f451Sopenharmony_ci * If there wasn't enough input to the next filter to fill 8860f66f451Sopenharmony_ci * the output buffer with unfiltered data, there's no point 8870f66f451Sopenharmony_ci * to try decoding more data to temp. 8880f66f451Sopenharmony_ci */ 8890f66f451Sopenharmony_ci if (b->out_pos + s->temp.size < b->out_size) 8900f66f451Sopenharmony_ci return XZ_OK; 8910f66f451Sopenharmony_ci } 8920f66f451Sopenharmony_ci 8930f66f451Sopenharmony_ci /* 8940f66f451Sopenharmony_ci * We have unfiltered data in temp. If the output buffer isn't full 8950f66f451Sopenharmony_ci * yet, try to fill the temp buffer by decoding more data from the 8960f66f451Sopenharmony_ci * next filter. Apply the BCJ filter on temp. Then we hopefully can 8970f66f451Sopenharmony_ci * fill the actual output buffer by copying filtered data from temp. 8980f66f451Sopenharmony_ci * A mix of filtered and unfiltered data may be left in temp; it will 8990f66f451Sopenharmony_ci * be taken care on the next call to this function. 9000f66f451Sopenharmony_ci */ 9010f66f451Sopenharmony_ci if (b->out_pos < b->out_size) { 9020f66f451Sopenharmony_ci /* Make b->out{,_pos,_size} temporarily point to s->temp. */ 9030f66f451Sopenharmony_ci s->out = b->out; 9040f66f451Sopenharmony_ci s->out_pos = b->out_pos; 9050f66f451Sopenharmony_ci s->out_size = b->out_size; 9060f66f451Sopenharmony_ci b->out = s->temp.buf; 9070f66f451Sopenharmony_ci b->out_pos = s->temp.size; 9080f66f451Sopenharmony_ci b->out_size = sizeof(s->temp.buf); 9090f66f451Sopenharmony_ci 9100f66f451Sopenharmony_ci s->ret = xz_dec_lzma2_run(lzma2, b); 9110f66f451Sopenharmony_ci 9120f66f451Sopenharmony_ci s->temp.size = b->out_pos; 9130f66f451Sopenharmony_ci b->out = s->out; 9140f66f451Sopenharmony_ci b->out_pos = s->out_pos; 9150f66f451Sopenharmony_ci b->out_size = s->out_size; 9160f66f451Sopenharmony_ci 9170f66f451Sopenharmony_ci if (s->ret != XZ_OK && s->ret != XZ_STREAM_END) 9180f66f451Sopenharmony_ci return s->ret; 9190f66f451Sopenharmony_ci 9200f66f451Sopenharmony_ci bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size); 9210f66f451Sopenharmony_ci 9220f66f451Sopenharmony_ci /* 9230f66f451Sopenharmony_ci * If the next filter returned XZ_STREAM_END, we mark that 9240f66f451Sopenharmony_ci * everything is filtered, since the last unfiltered bytes 9250f66f451Sopenharmony_ci * of the stream are meant to be left as is. 9260f66f451Sopenharmony_ci */ 9270f66f451Sopenharmony_ci if (s->ret == XZ_STREAM_END) 9280f66f451Sopenharmony_ci s->temp.filtered = s->temp.size; 9290f66f451Sopenharmony_ci 9300f66f451Sopenharmony_ci bcj_flush(s, b); 9310f66f451Sopenharmony_ci if (s->temp.filtered > 0) 9320f66f451Sopenharmony_ci return XZ_OK; 9330f66f451Sopenharmony_ci } 9340f66f451Sopenharmony_ci 9350f66f451Sopenharmony_ci return s->ret; 9360f66f451Sopenharmony_ci} 9370f66f451Sopenharmony_ci 9380f66f451Sopenharmony_cienum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id) 9390f66f451Sopenharmony_ci{ 9400f66f451Sopenharmony_ci switch (id) { 9410f66f451Sopenharmony_ci#ifdef XZ_DEC_X86 9420f66f451Sopenharmony_ci case BCJ_X86: 9430f66f451Sopenharmony_ci#endif 9440f66f451Sopenharmony_ci#ifdef XZ_DEC_POWERPC 9450f66f451Sopenharmony_ci case BCJ_POWERPC: 9460f66f451Sopenharmony_ci#endif 9470f66f451Sopenharmony_ci#ifdef XZ_DEC_IA64 9480f66f451Sopenharmony_ci case BCJ_IA64: 9490f66f451Sopenharmony_ci#endif 9500f66f451Sopenharmony_ci#ifdef XZ_DEC_ARM 9510f66f451Sopenharmony_ci case BCJ_ARM: 9520f66f451Sopenharmony_ci#endif 9530f66f451Sopenharmony_ci#ifdef XZ_DEC_ARMTHUMB 9540f66f451Sopenharmony_ci case BCJ_ARMTHUMB: 9550f66f451Sopenharmony_ci#endif 9560f66f451Sopenharmony_ci#ifdef XZ_DEC_SPARC 9570f66f451Sopenharmony_ci case BCJ_SPARC: 9580f66f451Sopenharmony_ci#endif 9590f66f451Sopenharmony_ci break; 9600f66f451Sopenharmony_ci 9610f66f451Sopenharmony_ci default: 9620f66f451Sopenharmony_ci /* Unsupported Filter ID */ 9630f66f451Sopenharmony_ci return XZ_OPTIONS_ERROR; 9640f66f451Sopenharmony_ci } 9650f66f451Sopenharmony_ci 9660f66f451Sopenharmony_ci s->type = id; 9670f66f451Sopenharmony_ci s->ret = XZ_OK; 9680f66f451Sopenharmony_ci s->pos = 0; 9690f66f451Sopenharmony_ci s->x86_prev_mask = 0; 9700f66f451Sopenharmony_ci s->temp.filtered = 0; 9710f66f451Sopenharmony_ci s->temp.size = 0; 9720f66f451Sopenharmony_ci 9730f66f451Sopenharmony_ci return XZ_OK; 9740f66f451Sopenharmony_ci} 9750f66f451Sopenharmony_ci 9760f66f451Sopenharmony_ci#endif 9770f66f451Sopenharmony_ci/* 9780f66f451Sopenharmony_ci * LZMA2 decoder 9790f66f451Sopenharmony_ci */ 9800f66f451Sopenharmony_ci 9810f66f451Sopenharmony_ci 9820f66f451Sopenharmony_ci// BEGIN xz_lzma2.h 9830f66f451Sopenharmony_ci/* 9840f66f451Sopenharmony_ci * LZMA2 definitions 9850f66f451Sopenharmony_ci * 9860f66f451Sopenharmony_ci */ 9870f66f451Sopenharmony_ci 9880f66f451Sopenharmony_ci 9890f66f451Sopenharmony_ci/* Range coder constants */ 9900f66f451Sopenharmony_ci#define RC_SHIFT_BITS 8 9910f66f451Sopenharmony_ci#define RC_TOP_BITS 24 9920f66f451Sopenharmony_ci#define RC_TOP_VALUE (1 << RC_TOP_BITS) 9930f66f451Sopenharmony_ci#define RC_BIT_MODEL_TOTAL_BITS 11 9940f66f451Sopenharmony_ci#define RC_BIT_MODEL_TOTAL (1 << RC_BIT_MODEL_TOTAL_BITS) 9950f66f451Sopenharmony_ci#define RC_MOVE_BITS 5 9960f66f451Sopenharmony_ci 9970f66f451Sopenharmony_ci/* 9980f66f451Sopenharmony_ci * Maximum number of position states. A position state is the lowest pb 9990f66f451Sopenharmony_ci * number of bits of the current uncompressed offset. In some places there 10000f66f451Sopenharmony_ci * are different sets of probabilities for different position states. 10010f66f451Sopenharmony_ci */ 10020f66f451Sopenharmony_ci#define POS_STATES_MAX (1 << 4) 10030f66f451Sopenharmony_ci 10040f66f451Sopenharmony_ci/* 10050f66f451Sopenharmony_ci * This enum is used to track which LZMA symbols have occurred most recently 10060f66f451Sopenharmony_ci * and in which order. This information is used to predict the next symbol. 10070f66f451Sopenharmony_ci * 10080f66f451Sopenharmony_ci * Symbols: 10090f66f451Sopenharmony_ci * - Literal: One 8-bit byte 10100f66f451Sopenharmony_ci * - Match: Repeat a chunk of data at some distance 10110f66f451Sopenharmony_ci * - Long repeat: Multi-byte match at a recently seen distance 10120f66f451Sopenharmony_ci * - Short repeat: One-byte repeat at a recently seen distance 10130f66f451Sopenharmony_ci * 10140f66f451Sopenharmony_ci * The symbol names are in from STATE_oldest_older_previous. REP means 10150f66f451Sopenharmony_ci * either short or long repeated match, and NONLIT means any non-literal. 10160f66f451Sopenharmony_ci */ 10170f66f451Sopenharmony_cienum lzma_state { 10180f66f451Sopenharmony_ci STATE_LIT_LIT, 10190f66f451Sopenharmony_ci STATE_MATCH_LIT_LIT, 10200f66f451Sopenharmony_ci STATE_REP_LIT_LIT, 10210f66f451Sopenharmony_ci STATE_SHORTREP_LIT_LIT, 10220f66f451Sopenharmony_ci STATE_MATCH_LIT, 10230f66f451Sopenharmony_ci STATE_REP_LIT, 10240f66f451Sopenharmony_ci STATE_SHORTREP_LIT, 10250f66f451Sopenharmony_ci STATE_LIT_MATCH, 10260f66f451Sopenharmony_ci STATE_LIT_LONGREP, 10270f66f451Sopenharmony_ci STATE_LIT_SHORTREP, 10280f66f451Sopenharmony_ci STATE_NONLIT_MATCH, 10290f66f451Sopenharmony_ci STATE_NONLIT_REP 10300f66f451Sopenharmony_ci}; 10310f66f451Sopenharmony_ci 10320f66f451Sopenharmony_ci/* Total number of states */ 10330f66f451Sopenharmony_ci#define STATES 12 10340f66f451Sopenharmony_ci 10350f66f451Sopenharmony_ci/* The lowest 7 states indicate that the previous state was a literal. */ 10360f66f451Sopenharmony_ci#define LIT_STATES 7 10370f66f451Sopenharmony_ci 10380f66f451Sopenharmony_ci/* Indicate that the latest symbol was a literal. */ 10390f66f451Sopenharmony_cistatic inline void lzma_state_literal(enum lzma_state *state) 10400f66f451Sopenharmony_ci{ 10410f66f451Sopenharmony_ci if (*state <= STATE_SHORTREP_LIT_LIT) 10420f66f451Sopenharmony_ci *state = STATE_LIT_LIT; 10430f66f451Sopenharmony_ci else if (*state <= STATE_LIT_SHORTREP) 10440f66f451Sopenharmony_ci *state -= 3; 10450f66f451Sopenharmony_ci else 10460f66f451Sopenharmony_ci *state -= 6; 10470f66f451Sopenharmony_ci} 10480f66f451Sopenharmony_ci 10490f66f451Sopenharmony_ci/* Indicate that the latest symbol was a match. */ 10500f66f451Sopenharmony_cistatic inline void lzma_state_match(enum lzma_state *state) 10510f66f451Sopenharmony_ci{ 10520f66f451Sopenharmony_ci *state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH; 10530f66f451Sopenharmony_ci} 10540f66f451Sopenharmony_ci 10550f66f451Sopenharmony_ci/* Indicate that the latest state was a long repeated match. */ 10560f66f451Sopenharmony_cistatic inline void lzma_state_long_rep(enum lzma_state *state) 10570f66f451Sopenharmony_ci{ 10580f66f451Sopenharmony_ci *state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP; 10590f66f451Sopenharmony_ci} 10600f66f451Sopenharmony_ci 10610f66f451Sopenharmony_ci/* Indicate that the latest symbol was a short match. */ 10620f66f451Sopenharmony_cistatic inline void lzma_state_short_rep(enum lzma_state *state) 10630f66f451Sopenharmony_ci{ 10640f66f451Sopenharmony_ci *state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP; 10650f66f451Sopenharmony_ci} 10660f66f451Sopenharmony_ci 10670f66f451Sopenharmony_ci/* Test if the previous symbol was a literal. */ 10680f66f451Sopenharmony_cistatic inline int lzma_state_is_literal(enum lzma_state state) 10690f66f451Sopenharmony_ci{ 10700f66f451Sopenharmony_ci return state < LIT_STATES; 10710f66f451Sopenharmony_ci} 10720f66f451Sopenharmony_ci 10730f66f451Sopenharmony_ci/* Each literal coder is divided in three sections: 10740f66f451Sopenharmony_ci * - 0x001-0x0FF: Without match byte 10750f66f451Sopenharmony_ci * - 0x101-0x1FF: With match byte; match bit is 0 10760f66f451Sopenharmony_ci * - 0x201-0x2FF: With match byte; match bit is 1 10770f66f451Sopenharmony_ci * 10780f66f451Sopenharmony_ci * Match byte is used when the previous LZMA symbol was something else than 10790f66f451Sopenharmony_ci * a literal (that is, it was some kind of match). 10800f66f451Sopenharmony_ci */ 10810f66f451Sopenharmony_ci#define LITERAL_CODER_SIZE 0x300 10820f66f451Sopenharmony_ci 10830f66f451Sopenharmony_ci/* Maximum number of literal coders */ 10840f66f451Sopenharmony_ci#define LITERAL_CODERS_MAX (1 << 4) 10850f66f451Sopenharmony_ci 10860f66f451Sopenharmony_ci/* Minimum length of a match is two bytes. */ 10870f66f451Sopenharmony_ci#define MATCH_LEN_MIN 2 10880f66f451Sopenharmony_ci 10890f66f451Sopenharmony_ci/* Match length is encoded with 4, 5, or 10 bits. 10900f66f451Sopenharmony_ci * 10910f66f451Sopenharmony_ci * Length Bits 10920f66f451Sopenharmony_ci * 2-9 4 = Choice=0 + 3 bits 10930f66f451Sopenharmony_ci * 10-17 5 = Choice=1 + Choice2=0 + 3 bits 10940f66f451Sopenharmony_ci * 18-273 10 = Choice=1 + Choice2=1 + 8 bits 10950f66f451Sopenharmony_ci */ 10960f66f451Sopenharmony_ci#define LEN_LOW_BITS 3 10970f66f451Sopenharmony_ci#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS) 10980f66f451Sopenharmony_ci#define LEN_MID_BITS 3 10990f66f451Sopenharmony_ci#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS) 11000f66f451Sopenharmony_ci#define LEN_HIGH_BITS 8 11010f66f451Sopenharmony_ci#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS) 11020f66f451Sopenharmony_ci#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS) 11030f66f451Sopenharmony_ci 11040f66f451Sopenharmony_ci/* 11050f66f451Sopenharmony_ci * Maximum length of a match is 273 which is a result of the encoding 11060f66f451Sopenharmony_ci * described above. 11070f66f451Sopenharmony_ci */ 11080f66f451Sopenharmony_ci#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1) 11090f66f451Sopenharmony_ci 11100f66f451Sopenharmony_ci/* 11110f66f451Sopenharmony_ci * Different sets of probabilities are used for match distances that have 11120f66f451Sopenharmony_ci * very short match length: Lengths of 2, 3, and 4 bytes have a separate 11130f66f451Sopenharmony_ci * set of probabilities for each length. The matches with longer length 11140f66f451Sopenharmony_ci * use a shared set of probabilities. 11150f66f451Sopenharmony_ci */ 11160f66f451Sopenharmony_ci#define DIST_STATES 4 11170f66f451Sopenharmony_ci 11180f66f451Sopenharmony_ci/* 11190f66f451Sopenharmony_ci * Get the index of the appropriate probability array for decoding 11200f66f451Sopenharmony_ci * the distance slot. 11210f66f451Sopenharmony_ci */ 11220f66f451Sopenharmony_cistatic inline uint32_t lzma_get_dist_state(uint32_t len) 11230f66f451Sopenharmony_ci{ 11240f66f451Sopenharmony_ci return len < DIST_STATES + MATCH_LEN_MIN 11250f66f451Sopenharmony_ci ? len - MATCH_LEN_MIN : DIST_STATES - 1; 11260f66f451Sopenharmony_ci} 11270f66f451Sopenharmony_ci 11280f66f451Sopenharmony_ci/* 11290f66f451Sopenharmony_ci * The highest two bits of a 32-bit match distance are encoded using six bits. 11300f66f451Sopenharmony_ci * This six-bit value is called a distance slot. This way encoding a 32-bit 11310f66f451Sopenharmony_ci * value takes 6-36 bits, larger values taking more bits. 11320f66f451Sopenharmony_ci */ 11330f66f451Sopenharmony_ci#define DIST_SLOT_BITS 6 11340f66f451Sopenharmony_ci#define DIST_SLOTS (1 << DIST_SLOT_BITS) 11350f66f451Sopenharmony_ci 11360f66f451Sopenharmony_ci/* Match distances up to 127 are fully encoded using probabilities. Since 11370f66f451Sopenharmony_ci * the highest two bits (distance slot) are always encoded using six bits, 11380f66f451Sopenharmony_ci * the distances 0-3 don't need any additional bits to encode, since the 11390f66f451Sopenharmony_ci * distance slot itself is the same as the actual distance. DIST_MODEL_START 11400f66f451Sopenharmony_ci * indicates the first distance slot where at least one additional bit is 11410f66f451Sopenharmony_ci * needed. 11420f66f451Sopenharmony_ci */ 11430f66f451Sopenharmony_ci#define DIST_MODEL_START 4 11440f66f451Sopenharmony_ci 11450f66f451Sopenharmony_ci/* 11460f66f451Sopenharmony_ci * Match distances greater than 127 are encoded in three pieces: 11470f66f451Sopenharmony_ci * - distance slot: the highest two bits 11480f66f451Sopenharmony_ci * - direct bits: 2-26 bits below the highest two bits 11490f66f451Sopenharmony_ci * - alignment bits: four lowest bits 11500f66f451Sopenharmony_ci * 11510f66f451Sopenharmony_ci * Direct bits don't use any probabilities. 11520f66f451Sopenharmony_ci * 11530f66f451Sopenharmony_ci * The distance slot value of 14 is for distances 128-191. 11540f66f451Sopenharmony_ci */ 11550f66f451Sopenharmony_ci#define DIST_MODEL_END 14 11560f66f451Sopenharmony_ci 11570f66f451Sopenharmony_ci/* Distance slots that indicate a distance <= 127. */ 11580f66f451Sopenharmony_ci#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2) 11590f66f451Sopenharmony_ci#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS) 11600f66f451Sopenharmony_ci 11610f66f451Sopenharmony_ci/* 11620f66f451Sopenharmony_ci * For match distances greater than 127, only the highest two bits and the 11630f66f451Sopenharmony_ci * lowest four bits (alignment) is encoded using probabilities. 11640f66f451Sopenharmony_ci */ 11650f66f451Sopenharmony_ci#define ALIGN_BITS 4 11660f66f451Sopenharmony_ci#define ALIGN_SIZE (1 << ALIGN_BITS) 11670f66f451Sopenharmony_ci#define ALIGN_MASK (ALIGN_SIZE - 1) 11680f66f451Sopenharmony_ci 11690f66f451Sopenharmony_ci/* Total number of all probability variables */ 11700f66f451Sopenharmony_ci#define PROBS_TOTAL (1846 + LITERAL_CODERS_MAX * LITERAL_CODER_SIZE) 11710f66f451Sopenharmony_ci 11720f66f451Sopenharmony_ci/* 11730f66f451Sopenharmony_ci * LZMA remembers the four most recent match distances. Reusing these 11740f66f451Sopenharmony_ci * distances tends to take less space than re-encoding the actual 11750f66f451Sopenharmony_ci * distance value. 11760f66f451Sopenharmony_ci */ 11770f66f451Sopenharmony_ci#define REPS 4 11780f66f451Sopenharmony_ci 11790f66f451Sopenharmony_ci 11800f66f451Sopenharmony_ci// END xz_lzma2.h 11810f66f451Sopenharmony_ci 11820f66f451Sopenharmony_ci/* 11830f66f451Sopenharmony_ci * Range decoder initialization eats the first five bytes of each LZMA chunk. 11840f66f451Sopenharmony_ci */ 11850f66f451Sopenharmony_ci#define RC_INIT_BYTES 5 11860f66f451Sopenharmony_ci 11870f66f451Sopenharmony_ci/* 11880f66f451Sopenharmony_ci * Minimum number of usable input buffer to safely decode one LZMA symbol. 11890f66f451Sopenharmony_ci * The worst case is that we decode 22 bits using probabilities and 26 11900f66f451Sopenharmony_ci * direct bits. This may decode at maximum of 20 bytes of input. However, 11910f66f451Sopenharmony_ci * lzma_main() does an extra normalization before returning, thus we 11920f66f451Sopenharmony_ci * need to put 21 here. 11930f66f451Sopenharmony_ci */ 11940f66f451Sopenharmony_ci#define LZMA_IN_REQUIRED 21 11950f66f451Sopenharmony_ci 11960f66f451Sopenharmony_ci/* 11970f66f451Sopenharmony_ci * Dictionary (history buffer) 11980f66f451Sopenharmony_ci * 11990f66f451Sopenharmony_ci * These are always true: 12000f66f451Sopenharmony_ci * start <= pos <= full <= end 12010f66f451Sopenharmony_ci * pos <= limit <= end 12020f66f451Sopenharmony_ci * end == size 12030f66f451Sopenharmony_ci * size <= size_max 12040f66f451Sopenharmony_ci * allocated <= size 12050f66f451Sopenharmony_ci * 12060f66f451Sopenharmony_ci * Most of these variables are size_t as a relic of single-call mode, 12070f66f451Sopenharmony_ci * in which the dictionary variables address the actual output 12080f66f451Sopenharmony_ci * buffer directly. 12090f66f451Sopenharmony_ci */ 12100f66f451Sopenharmony_cistruct dictionary { 12110f66f451Sopenharmony_ci /* Beginning of the history buffer */ 12120f66f451Sopenharmony_ci uint8_t *buf; 12130f66f451Sopenharmony_ci 12140f66f451Sopenharmony_ci /* Old position in buf (before decoding more data) */ 12150f66f451Sopenharmony_ci size_t start; 12160f66f451Sopenharmony_ci 12170f66f451Sopenharmony_ci /* Position in buf */ 12180f66f451Sopenharmony_ci size_t pos; 12190f66f451Sopenharmony_ci 12200f66f451Sopenharmony_ci /* 12210f66f451Sopenharmony_ci * How full dictionary is. This is used to detect corrupt input that 12220f66f451Sopenharmony_ci * would read beyond the beginning of the uncompressed stream. 12230f66f451Sopenharmony_ci */ 12240f66f451Sopenharmony_ci size_t full; 12250f66f451Sopenharmony_ci 12260f66f451Sopenharmony_ci /* Write limit; we don't write to buf[limit] or later bytes. */ 12270f66f451Sopenharmony_ci size_t limit; 12280f66f451Sopenharmony_ci 12290f66f451Sopenharmony_ci /* End of the dictionary buffer. This is the same as the dictionary size. */ 12300f66f451Sopenharmony_ci size_t end; 12310f66f451Sopenharmony_ci 12320f66f451Sopenharmony_ci /* 12330f66f451Sopenharmony_ci * Size of the dictionary as specified in Block Header. This is used 12340f66f451Sopenharmony_ci * together with "full" to detect corrupt input that would make us 12350f66f451Sopenharmony_ci * read beyond the beginning of the uncompressed stream. 12360f66f451Sopenharmony_ci */ 12370f66f451Sopenharmony_ci uint32_t size; 12380f66f451Sopenharmony_ci 12390f66f451Sopenharmony_ci /* 12400f66f451Sopenharmony_ci * Maximum allowed dictionary size. 12410f66f451Sopenharmony_ci */ 12420f66f451Sopenharmony_ci uint32_t size_max; 12430f66f451Sopenharmony_ci 12440f66f451Sopenharmony_ci /* 12450f66f451Sopenharmony_ci * Amount of memory currently allocated for the dictionary. 12460f66f451Sopenharmony_ci */ 12470f66f451Sopenharmony_ci uint32_t allocated; 12480f66f451Sopenharmony_ci}; 12490f66f451Sopenharmony_ci 12500f66f451Sopenharmony_ci/* Range decoder */ 12510f66f451Sopenharmony_cistruct rc_dec { 12520f66f451Sopenharmony_ci uint32_t range; 12530f66f451Sopenharmony_ci uint32_t code; 12540f66f451Sopenharmony_ci 12550f66f451Sopenharmony_ci /* 12560f66f451Sopenharmony_ci * Number of initializing bytes remaining to be read 12570f66f451Sopenharmony_ci * by rc_read_init(). 12580f66f451Sopenharmony_ci */ 12590f66f451Sopenharmony_ci uint32_t init_bytes_left; 12600f66f451Sopenharmony_ci 12610f66f451Sopenharmony_ci /* 12620f66f451Sopenharmony_ci * Buffer from which we read our input. It can be either 12630f66f451Sopenharmony_ci * temp.buf or the caller-provided input buffer. 12640f66f451Sopenharmony_ci */ 12650f66f451Sopenharmony_ci const uint8_t *in; 12660f66f451Sopenharmony_ci size_t in_pos; 12670f66f451Sopenharmony_ci size_t in_limit; 12680f66f451Sopenharmony_ci}; 12690f66f451Sopenharmony_ci 12700f66f451Sopenharmony_ci/* Probabilities for a length decoder. */ 12710f66f451Sopenharmony_cistruct lzma_len_dec { 12720f66f451Sopenharmony_ci /* Probability of match length being at least 10 */ 12730f66f451Sopenharmony_ci uint16_t choice; 12740f66f451Sopenharmony_ci 12750f66f451Sopenharmony_ci /* Probability of match length being at least 18 */ 12760f66f451Sopenharmony_ci uint16_t choice2; 12770f66f451Sopenharmony_ci 12780f66f451Sopenharmony_ci /* Probabilities for match lengths 2-9 */ 12790f66f451Sopenharmony_ci uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS]; 12800f66f451Sopenharmony_ci 12810f66f451Sopenharmony_ci /* Probabilities for match lengths 10-17 */ 12820f66f451Sopenharmony_ci uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS]; 12830f66f451Sopenharmony_ci 12840f66f451Sopenharmony_ci /* Probabilities for match lengths 18-273 */ 12850f66f451Sopenharmony_ci uint16_t high[LEN_HIGH_SYMBOLS]; 12860f66f451Sopenharmony_ci}; 12870f66f451Sopenharmony_ci 12880f66f451Sopenharmony_cistruct lzma_dec { 12890f66f451Sopenharmony_ci /* Distances of latest four matches */ 12900f66f451Sopenharmony_ci uint32_t rep0; 12910f66f451Sopenharmony_ci uint32_t rep1; 12920f66f451Sopenharmony_ci uint32_t rep2; 12930f66f451Sopenharmony_ci uint32_t rep3; 12940f66f451Sopenharmony_ci 12950f66f451Sopenharmony_ci /* Types of the most recently seen LZMA symbols */ 12960f66f451Sopenharmony_ci enum lzma_state state; 12970f66f451Sopenharmony_ci 12980f66f451Sopenharmony_ci /* 12990f66f451Sopenharmony_ci * Length of a match. This is updated so that dict_repeat can 13000f66f451Sopenharmony_ci * be called again to finish repeating the whole match. 13010f66f451Sopenharmony_ci */ 13020f66f451Sopenharmony_ci uint32_t len; 13030f66f451Sopenharmony_ci 13040f66f451Sopenharmony_ci /* 13050f66f451Sopenharmony_ci * LZMA properties or related bit masks (number of literal 13060f66f451Sopenharmony_ci * context bits, a mask dervied from the number of literal 13070f66f451Sopenharmony_ci * position bits, and a mask dervied from the number 13080f66f451Sopenharmony_ci * position bits) 13090f66f451Sopenharmony_ci */ 13100f66f451Sopenharmony_ci uint32_t lc; 13110f66f451Sopenharmony_ci uint32_t literal_pos_mask; /* (1 << lp) - 1 */ 13120f66f451Sopenharmony_ci uint32_t pos_mask; /* (1 << pb) - 1 */ 13130f66f451Sopenharmony_ci 13140f66f451Sopenharmony_ci /* If 1, it's a match. Otherwise it's a single 8-bit literal. */ 13150f66f451Sopenharmony_ci uint16_t is_match[STATES][POS_STATES_MAX]; 13160f66f451Sopenharmony_ci 13170f66f451Sopenharmony_ci /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */ 13180f66f451Sopenharmony_ci uint16_t is_rep[STATES]; 13190f66f451Sopenharmony_ci 13200f66f451Sopenharmony_ci /* 13210f66f451Sopenharmony_ci * If 0, distance of a repeated match is rep0. 13220f66f451Sopenharmony_ci * Otherwise check is_rep1. 13230f66f451Sopenharmony_ci */ 13240f66f451Sopenharmony_ci uint16_t is_rep0[STATES]; 13250f66f451Sopenharmony_ci 13260f66f451Sopenharmony_ci /* 13270f66f451Sopenharmony_ci * If 0, distance of a repeated match is rep1. 13280f66f451Sopenharmony_ci * Otherwise check is_rep2. 13290f66f451Sopenharmony_ci */ 13300f66f451Sopenharmony_ci uint16_t is_rep1[STATES]; 13310f66f451Sopenharmony_ci 13320f66f451Sopenharmony_ci /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */ 13330f66f451Sopenharmony_ci uint16_t is_rep2[STATES]; 13340f66f451Sopenharmony_ci 13350f66f451Sopenharmony_ci /* 13360f66f451Sopenharmony_ci * If 1, the repeated match has length of one byte. Otherwise 13370f66f451Sopenharmony_ci * the length is decoded from rep_len_decoder. 13380f66f451Sopenharmony_ci */ 13390f66f451Sopenharmony_ci uint16_t is_rep0_long[STATES][POS_STATES_MAX]; 13400f66f451Sopenharmony_ci 13410f66f451Sopenharmony_ci /* 13420f66f451Sopenharmony_ci * Probability tree for the highest two bits of the match 13430f66f451Sopenharmony_ci * distance. There is a separate probability tree for match 13440f66f451Sopenharmony_ci * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273]. 13450f66f451Sopenharmony_ci */ 13460f66f451Sopenharmony_ci uint16_t dist_slot[DIST_STATES][DIST_SLOTS]; 13470f66f451Sopenharmony_ci 13480f66f451Sopenharmony_ci /* 13490f66f451Sopenharmony_ci * Probility trees for additional bits for match distance 13500f66f451Sopenharmony_ci * when the distance is in the range [4, 127]. 13510f66f451Sopenharmony_ci */ 13520f66f451Sopenharmony_ci uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END]; 13530f66f451Sopenharmony_ci 13540f66f451Sopenharmony_ci /* 13550f66f451Sopenharmony_ci * Probability tree for the lowest four bits of a match 13560f66f451Sopenharmony_ci * distance that is equal to or greater than 128. 13570f66f451Sopenharmony_ci */ 13580f66f451Sopenharmony_ci uint16_t dist_align[ALIGN_SIZE]; 13590f66f451Sopenharmony_ci 13600f66f451Sopenharmony_ci /* Length of a normal match */ 13610f66f451Sopenharmony_ci struct lzma_len_dec match_len_dec; 13620f66f451Sopenharmony_ci 13630f66f451Sopenharmony_ci /* Length of a repeated match */ 13640f66f451Sopenharmony_ci struct lzma_len_dec rep_len_dec; 13650f66f451Sopenharmony_ci 13660f66f451Sopenharmony_ci /* Probabilities of literals */ 13670f66f451Sopenharmony_ci uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; 13680f66f451Sopenharmony_ci}; 13690f66f451Sopenharmony_ci 13700f66f451Sopenharmony_cistruct lzma2_dec { 13710f66f451Sopenharmony_ci /* Position in xz_dec_lzma2_run(). */ 13720f66f451Sopenharmony_ci enum lzma2_seq { 13730f66f451Sopenharmony_ci SEQ_CONTROL, 13740f66f451Sopenharmony_ci SEQ_UNCOMPRESSED_1, 13750f66f451Sopenharmony_ci SEQ_UNCOMPRESSED_2, 13760f66f451Sopenharmony_ci SEQ_COMPRESSED_0, 13770f66f451Sopenharmony_ci SEQ_COMPRESSED_1, 13780f66f451Sopenharmony_ci SEQ_PROPERTIES, 13790f66f451Sopenharmony_ci SEQ_LZMA_PREPARE, 13800f66f451Sopenharmony_ci SEQ_LZMA_RUN, 13810f66f451Sopenharmony_ci SEQ_COPY 13820f66f451Sopenharmony_ci } sequence; 13830f66f451Sopenharmony_ci 13840f66f451Sopenharmony_ci /* Next position after decoding the compressed size of the chunk. */ 13850f66f451Sopenharmony_ci enum lzma2_seq next_sequence; 13860f66f451Sopenharmony_ci 13870f66f451Sopenharmony_ci /* Uncompressed size of LZMA chunk (2 MiB at maximum) */ 13880f66f451Sopenharmony_ci uint32_t uncompressed; 13890f66f451Sopenharmony_ci 13900f66f451Sopenharmony_ci /* 13910f66f451Sopenharmony_ci * Compressed size of LZMA chunk or compressed/uncompressed 13920f66f451Sopenharmony_ci * size of uncompressed chunk (64 KiB at maximum) 13930f66f451Sopenharmony_ci */ 13940f66f451Sopenharmony_ci uint32_t compressed; 13950f66f451Sopenharmony_ci 13960f66f451Sopenharmony_ci /* 13970f66f451Sopenharmony_ci * True if dictionary reset is needed. This is false before 13980f66f451Sopenharmony_ci * the first chunk (LZMA or uncompressed). 13990f66f451Sopenharmony_ci */ 14000f66f451Sopenharmony_ci int need_dict_reset; 14010f66f451Sopenharmony_ci 14020f66f451Sopenharmony_ci /* 14030f66f451Sopenharmony_ci * True if new LZMA properties are needed. This is false 14040f66f451Sopenharmony_ci * before the first LZMA chunk. 14050f66f451Sopenharmony_ci */ 14060f66f451Sopenharmony_ci int need_props; 14070f66f451Sopenharmony_ci}; 14080f66f451Sopenharmony_ci 14090f66f451Sopenharmony_cistruct xz_dec_lzma2 { 14100f66f451Sopenharmony_ci /* 14110f66f451Sopenharmony_ci * The order below is important on x86 to reduce code size and 14120f66f451Sopenharmony_ci * it shouldn't hurt on other platforms. Everything up to and 14130f66f451Sopenharmony_ci * including lzma.pos_mask are in the first 128 bytes on x86-32, 14140f66f451Sopenharmony_ci * which allows using smaller instructions to access those 14150f66f451Sopenharmony_ci * variables. On x86-64, fewer variables fit into the first 128 14160f66f451Sopenharmony_ci * bytes, but this is still the best order without sacrificing 14170f66f451Sopenharmony_ci * the readability by splitting the structures. 14180f66f451Sopenharmony_ci */ 14190f66f451Sopenharmony_ci struct rc_dec rc; 14200f66f451Sopenharmony_ci struct dictionary dict; 14210f66f451Sopenharmony_ci struct lzma2_dec lzma2; 14220f66f451Sopenharmony_ci struct lzma_dec lzma; 14230f66f451Sopenharmony_ci 14240f66f451Sopenharmony_ci /* 14250f66f451Sopenharmony_ci * Temporary buffer which holds small number of input bytes between 14260f66f451Sopenharmony_ci * decoder calls. See lzma2_lzma() for details. 14270f66f451Sopenharmony_ci */ 14280f66f451Sopenharmony_ci struct { 14290f66f451Sopenharmony_ci uint32_t size; 14300f66f451Sopenharmony_ci uint8_t buf[3 * LZMA_IN_REQUIRED]; 14310f66f451Sopenharmony_ci } temp; 14320f66f451Sopenharmony_ci}; 14330f66f451Sopenharmony_ci 14340f66f451Sopenharmony_ci/************** 14350f66f451Sopenharmony_ci * Dictionary * 14360f66f451Sopenharmony_ci **************/ 14370f66f451Sopenharmony_ci 14380f66f451Sopenharmony_ci/* Reset the dictionary state. */ 14390f66f451Sopenharmony_cistatic void dict_reset(struct dictionary *dict) 14400f66f451Sopenharmony_ci{ 14410f66f451Sopenharmony_ci dict->start = 0; 14420f66f451Sopenharmony_ci dict->pos = 0; 14430f66f451Sopenharmony_ci dict->limit = 0; 14440f66f451Sopenharmony_ci dict->full = 0; 14450f66f451Sopenharmony_ci} 14460f66f451Sopenharmony_ci 14470f66f451Sopenharmony_ci/* Set dictionary write limit */ 14480f66f451Sopenharmony_cistatic void dict_limit(struct dictionary *dict, size_t out_max) 14490f66f451Sopenharmony_ci{ 14500f66f451Sopenharmony_ci if (dict->end - dict->pos <= out_max) 14510f66f451Sopenharmony_ci dict->limit = dict->end; 14520f66f451Sopenharmony_ci else 14530f66f451Sopenharmony_ci dict->limit = dict->pos + out_max; 14540f66f451Sopenharmony_ci} 14550f66f451Sopenharmony_ci 14560f66f451Sopenharmony_ci/* Return true if at least one byte can be written into the dictionary. */ 14570f66f451Sopenharmony_cistatic inline int dict_has_space(const struct dictionary *dict) 14580f66f451Sopenharmony_ci{ 14590f66f451Sopenharmony_ci return dict->pos < dict->limit; 14600f66f451Sopenharmony_ci} 14610f66f451Sopenharmony_ci 14620f66f451Sopenharmony_ci/* 14630f66f451Sopenharmony_ci * Get a byte from the dictionary at the given distance. The distance is 14640f66f451Sopenharmony_ci * assumed to valid, or as a special case, zero when the dictionary is 14650f66f451Sopenharmony_ci * still empty. This special case is needed for single-call decoding to 14660f66f451Sopenharmony_ci * avoid writing a '\0' to the end of the destination buffer. 14670f66f451Sopenharmony_ci */ 14680f66f451Sopenharmony_cistatic inline uint32_t dict_get(const struct dictionary *dict, uint32_t dist) 14690f66f451Sopenharmony_ci{ 14700f66f451Sopenharmony_ci size_t offset = dict->pos - dist - 1; 14710f66f451Sopenharmony_ci 14720f66f451Sopenharmony_ci if (dist >= dict->pos) 14730f66f451Sopenharmony_ci offset += dict->end; 14740f66f451Sopenharmony_ci 14750f66f451Sopenharmony_ci return dict->full > 0 ? dict->buf[offset] : 0; 14760f66f451Sopenharmony_ci} 14770f66f451Sopenharmony_ci 14780f66f451Sopenharmony_ci/* 14790f66f451Sopenharmony_ci * Put one byte into the dictionary. It is assumed that there is space for it. 14800f66f451Sopenharmony_ci */ 14810f66f451Sopenharmony_cistatic inline void dict_put(struct dictionary *dict, uint8_t byte) 14820f66f451Sopenharmony_ci{ 14830f66f451Sopenharmony_ci dict->buf[dict->pos++] = byte; 14840f66f451Sopenharmony_ci 14850f66f451Sopenharmony_ci if (dict->full < dict->pos) 14860f66f451Sopenharmony_ci dict->full = dict->pos; 14870f66f451Sopenharmony_ci} 14880f66f451Sopenharmony_ci 14890f66f451Sopenharmony_ci/* 14900f66f451Sopenharmony_ci * Repeat given number of bytes from the given distance. If the distance is 14910f66f451Sopenharmony_ci * invalid, false is returned. On success, true is returned and *len is 14920f66f451Sopenharmony_ci * updated to indicate how many bytes were left to be repeated. 14930f66f451Sopenharmony_ci */ 14940f66f451Sopenharmony_cistatic int dict_repeat(struct dictionary *dict, uint32_t *len, uint32_t dist) 14950f66f451Sopenharmony_ci{ 14960f66f451Sopenharmony_ci size_t back; 14970f66f451Sopenharmony_ci uint32_t left; 14980f66f451Sopenharmony_ci 14990f66f451Sopenharmony_ci if (dist >= dict->full || dist >= dict->size) return 0; 15000f66f451Sopenharmony_ci 15010f66f451Sopenharmony_ci left = minof(dict->limit - dict->pos, *len); 15020f66f451Sopenharmony_ci *len -= left; 15030f66f451Sopenharmony_ci 15040f66f451Sopenharmony_ci back = dict->pos - dist - 1; 15050f66f451Sopenharmony_ci if (dist >= dict->pos) 15060f66f451Sopenharmony_ci back += dict->end; 15070f66f451Sopenharmony_ci 15080f66f451Sopenharmony_ci do { 15090f66f451Sopenharmony_ci dict->buf[dict->pos++] = dict->buf[back++]; 15100f66f451Sopenharmony_ci if (back == dict->end) 15110f66f451Sopenharmony_ci back = 0; 15120f66f451Sopenharmony_ci } while (--left > 0); 15130f66f451Sopenharmony_ci 15140f66f451Sopenharmony_ci if (dict->full < dict->pos) 15150f66f451Sopenharmony_ci dict->full = dict->pos; 15160f66f451Sopenharmony_ci 15170f66f451Sopenharmony_ci return 1; 15180f66f451Sopenharmony_ci} 15190f66f451Sopenharmony_ci 15200f66f451Sopenharmony_ci/* Copy uncompressed data as is from input to dictionary and output buffers. */ 15210f66f451Sopenharmony_cistatic void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, 15220f66f451Sopenharmony_ci uint32_t *left) 15230f66f451Sopenharmony_ci{ 15240f66f451Sopenharmony_ci size_t copy_size; 15250f66f451Sopenharmony_ci 15260f66f451Sopenharmony_ci while (*left > 0 && b->in_pos < b->in_size 15270f66f451Sopenharmony_ci && b->out_pos < b->out_size) { 15280f66f451Sopenharmony_ci copy_size = minof(b->in_size - b->in_pos, 15290f66f451Sopenharmony_ci b->out_size - b->out_pos); 15300f66f451Sopenharmony_ci if (copy_size > dict->end - dict->pos) 15310f66f451Sopenharmony_ci copy_size = dict->end - dict->pos; 15320f66f451Sopenharmony_ci if (copy_size > *left) 15330f66f451Sopenharmony_ci copy_size = *left; 15340f66f451Sopenharmony_ci 15350f66f451Sopenharmony_ci *left -= copy_size; 15360f66f451Sopenharmony_ci 15370f66f451Sopenharmony_ci memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size); 15380f66f451Sopenharmony_ci dict->pos += copy_size; 15390f66f451Sopenharmony_ci 15400f66f451Sopenharmony_ci if (dict->full < dict->pos) 15410f66f451Sopenharmony_ci dict->full = dict->pos; 15420f66f451Sopenharmony_ci 15430f66f451Sopenharmony_ci if (dict->pos == dict->end) 15440f66f451Sopenharmony_ci dict->pos = 0; 15450f66f451Sopenharmony_ci 15460f66f451Sopenharmony_ci memcpy(b->out + b->out_pos, b->in + b->in_pos, 15470f66f451Sopenharmony_ci copy_size); 15480f66f451Sopenharmony_ci 15490f66f451Sopenharmony_ci dict->start = dict->pos; 15500f66f451Sopenharmony_ci 15510f66f451Sopenharmony_ci b->out_pos += copy_size; 15520f66f451Sopenharmony_ci b->in_pos += copy_size; 15530f66f451Sopenharmony_ci } 15540f66f451Sopenharmony_ci} 15550f66f451Sopenharmony_ci 15560f66f451Sopenharmony_ci/* 15570f66f451Sopenharmony_ci * Flush pending data from dictionary to b->out. It is assumed that there is 15580f66f451Sopenharmony_ci * enough space in b->out. This is guaranteed because caller uses dict_limit() 15590f66f451Sopenharmony_ci * before decoding data into the dictionary. 15600f66f451Sopenharmony_ci */ 15610f66f451Sopenharmony_cistatic uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) 15620f66f451Sopenharmony_ci{ 15630f66f451Sopenharmony_ci size_t copy_size = dict->pos - dict->start; 15640f66f451Sopenharmony_ci 15650f66f451Sopenharmony_ci if (dict->pos == dict->end) 15660f66f451Sopenharmony_ci dict->pos = 0; 15670f66f451Sopenharmony_ci 15680f66f451Sopenharmony_ci memcpy(b->out + b->out_pos, dict->buf + dict->start, 15690f66f451Sopenharmony_ci copy_size); 15700f66f451Sopenharmony_ci 15710f66f451Sopenharmony_ci dict->start = dict->pos; 15720f66f451Sopenharmony_ci b->out_pos += copy_size; 15730f66f451Sopenharmony_ci return copy_size; 15740f66f451Sopenharmony_ci} 15750f66f451Sopenharmony_ci 15760f66f451Sopenharmony_ci/***************** 15770f66f451Sopenharmony_ci * Range decoder * 15780f66f451Sopenharmony_ci *****************/ 15790f66f451Sopenharmony_ci 15800f66f451Sopenharmony_ci/* Reset the range decoder. */ 15810f66f451Sopenharmony_cistatic void rc_reset(struct rc_dec *rc) 15820f66f451Sopenharmony_ci{ 15830f66f451Sopenharmony_ci rc->range = (uint32_t)-1; 15840f66f451Sopenharmony_ci rc->code = 0; 15850f66f451Sopenharmony_ci rc->init_bytes_left = RC_INIT_BYTES; 15860f66f451Sopenharmony_ci} 15870f66f451Sopenharmony_ci 15880f66f451Sopenharmony_ci/* 15890f66f451Sopenharmony_ci * Read the first five initial bytes into rc->code if they haven't been 15900f66f451Sopenharmony_ci * read already. (Yes, the first byte gets completely ignored.) 15910f66f451Sopenharmony_ci */ 15920f66f451Sopenharmony_cistatic int rc_read_init(struct rc_dec *rc, struct xz_buf *b) 15930f66f451Sopenharmony_ci{ 15940f66f451Sopenharmony_ci while (rc->init_bytes_left > 0) { 15950f66f451Sopenharmony_ci if (b->in_pos == b->in_size) return 0; 15960f66f451Sopenharmony_ci 15970f66f451Sopenharmony_ci rc->code = (rc->code << 8) + b->in[b->in_pos++]; 15980f66f451Sopenharmony_ci --rc->init_bytes_left; 15990f66f451Sopenharmony_ci } 16000f66f451Sopenharmony_ci 16010f66f451Sopenharmony_ci return 1; 16020f66f451Sopenharmony_ci} 16030f66f451Sopenharmony_ci 16040f66f451Sopenharmony_ci/* Return true if there may not be enough input for the next decoding loop. */ 16050f66f451Sopenharmony_cistatic inline int rc_limit_exceeded(const struct rc_dec *rc) 16060f66f451Sopenharmony_ci{ 16070f66f451Sopenharmony_ci return rc->in_pos > rc->in_limit; 16080f66f451Sopenharmony_ci} 16090f66f451Sopenharmony_ci 16100f66f451Sopenharmony_ci/* 16110f66f451Sopenharmony_ci * Return true if it is possible (from point of view of range decoder) that 16120f66f451Sopenharmony_ci * we have reached the end of the LZMA chunk. 16130f66f451Sopenharmony_ci */ 16140f66f451Sopenharmony_cistatic inline int rc_is_finished(const struct rc_dec *rc) 16150f66f451Sopenharmony_ci{ 16160f66f451Sopenharmony_ci return rc->code == 0; 16170f66f451Sopenharmony_ci} 16180f66f451Sopenharmony_ci 16190f66f451Sopenharmony_ci/* Read the next input byte if needed. */ 16200f66f451Sopenharmony_cistatic inline void rc_normalize(struct rc_dec *rc) 16210f66f451Sopenharmony_ci{ 16220f66f451Sopenharmony_ci if (rc->range < RC_TOP_VALUE) { 16230f66f451Sopenharmony_ci rc->range <<= RC_SHIFT_BITS; 16240f66f451Sopenharmony_ci rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++]; 16250f66f451Sopenharmony_ci } 16260f66f451Sopenharmony_ci} 16270f66f451Sopenharmony_ci 16280f66f451Sopenharmony_ci/* 16290f66f451Sopenharmony_ci * Decode one bit. In some versions, this function has been splitted in three 16300f66f451Sopenharmony_ci * functions so that the compiler is supposed to be able to more easily avoid 16310f66f451Sopenharmony_ci * an extra branch. In this particular version of the LZMA decoder, this 16320f66f451Sopenharmony_ci * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 16330f66f451Sopenharmony_ci * on x86). Using a non-splitted version results in nicer looking code too. 16340f66f451Sopenharmony_ci * 16350f66f451Sopenharmony_ci * NOTE: This must return an int. Do not make it return a bool or the speed 16360f66f451Sopenharmony_ci * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care, 16370f66f451Sopenharmony_ci * and it generates 10-20 % faster code than GCC 3.x from this file anyway.) 16380f66f451Sopenharmony_ci */ 16390f66f451Sopenharmony_cistatic inline int rc_bit(struct rc_dec *rc, uint16_t *prob) 16400f66f451Sopenharmony_ci{ 16410f66f451Sopenharmony_ci uint32_t bound; 16420f66f451Sopenharmony_ci int bit; 16430f66f451Sopenharmony_ci 16440f66f451Sopenharmony_ci rc_normalize(rc); 16450f66f451Sopenharmony_ci bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob; 16460f66f451Sopenharmony_ci if (rc->code < bound) { 16470f66f451Sopenharmony_ci rc->range = bound; 16480f66f451Sopenharmony_ci *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS; 16490f66f451Sopenharmony_ci bit = 0; 16500f66f451Sopenharmony_ci } else { 16510f66f451Sopenharmony_ci rc->range -= bound; 16520f66f451Sopenharmony_ci rc->code -= bound; 16530f66f451Sopenharmony_ci *prob -= *prob >> RC_MOVE_BITS; 16540f66f451Sopenharmony_ci bit = 1; 16550f66f451Sopenharmony_ci } 16560f66f451Sopenharmony_ci 16570f66f451Sopenharmony_ci return bit; 16580f66f451Sopenharmony_ci} 16590f66f451Sopenharmony_ci 16600f66f451Sopenharmony_ci/* Decode a bittree starting from the most significant bit. */ 16610f66f451Sopenharmony_cistatic inline uint32_t rc_bittree(struct rc_dec *rc, 16620f66f451Sopenharmony_ci uint16_t *probs, uint32_t limit) 16630f66f451Sopenharmony_ci{ 16640f66f451Sopenharmony_ci uint32_t symbol = 1; 16650f66f451Sopenharmony_ci 16660f66f451Sopenharmony_ci do { 16670f66f451Sopenharmony_ci if (rc_bit(rc, &probs[symbol])) 16680f66f451Sopenharmony_ci symbol = (symbol << 1) + 1; 16690f66f451Sopenharmony_ci else 16700f66f451Sopenharmony_ci symbol <<= 1; 16710f66f451Sopenharmony_ci } while (symbol < limit); 16720f66f451Sopenharmony_ci 16730f66f451Sopenharmony_ci return symbol; 16740f66f451Sopenharmony_ci} 16750f66f451Sopenharmony_ci 16760f66f451Sopenharmony_ci/* Decode a bittree starting from the least significant bit. */ 16770f66f451Sopenharmony_cistatic inline void rc_bittree_reverse(struct rc_dec *rc, 16780f66f451Sopenharmony_ci uint16_t *probs, 16790f66f451Sopenharmony_ci uint32_t *dest, uint32_t limit) 16800f66f451Sopenharmony_ci{ 16810f66f451Sopenharmony_ci uint32_t symbol = 1; 16820f66f451Sopenharmony_ci uint32_t i = 0; 16830f66f451Sopenharmony_ci 16840f66f451Sopenharmony_ci do { 16850f66f451Sopenharmony_ci if (rc_bit(rc, &probs[symbol])) { 16860f66f451Sopenharmony_ci symbol = (symbol << 1) + 1; 16870f66f451Sopenharmony_ci *dest += 1 << i; 16880f66f451Sopenharmony_ci } else { 16890f66f451Sopenharmony_ci symbol <<= 1; 16900f66f451Sopenharmony_ci } 16910f66f451Sopenharmony_ci } while (++i < limit); 16920f66f451Sopenharmony_ci} 16930f66f451Sopenharmony_ci 16940f66f451Sopenharmony_ci/* Decode direct bits (fixed fifty-fifty probability) */ 16950f66f451Sopenharmony_cistatic inline void rc_direct(struct rc_dec *rc, uint32_t *dest, uint32_t limit) 16960f66f451Sopenharmony_ci{ 16970f66f451Sopenharmony_ci uint32_t mask; 16980f66f451Sopenharmony_ci 16990f66f451Sopenharmony_ci do { 17000f66f451Sopenharmony_ci rc_normalize(rc); 17010f66f451Sopenharmony_ci rc->range >>= 1; 17020f66f451Sopenharmony_ci rc->code -= rc->range; 17030f66f451Sopenharmony_ci mask = (uint32_t)0 - (rc->code >> 31); 17040f66f451Sopenharmony_ci rc->code += rc->range & mask; 17050f66f451Sopenharmony_ci *dest = (*dest << 1) + (mask + 1); 17060f66f451Sopenharmony_ci } while (--limit > 0); 17070f66f451Sopenharmony_ci} 17080f66f451Sopenharmony_ci 17090f66f451Sopenharmony_ci/******** 17100f66f451Sopenharmony_ci * LZMA * 17110f66f451Sopenharmony_ci ********/ 17120f66f451Sopenharmony_ci 17130f66f451Sopenharmony_ci/* Get pointer to literal coder probability array. */ 17140f66f451Sopenharmony_cistatic uint16_t *lzma_literal_probs(struct xz_dec_lzma2 *s) 17150f66f451Sopenharmony_ci{ 17160f66f451Sopenharmony_ci uint32_t prev_byte = dict_get(&s->dict, 0); 17170f66f451Sopenharmony_ci uint32_t low = prev_byte >> (8 - s->lzma.lc); 17180f66f451Sopenharmony_ci uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc; 17190f66f451Sopenharmony_ci return s->lzma.literal[low + high]; 17200f66f451Sopenharmony_ci} 17210f66f451Sopenharmony_ci 17220f66f451Sopenharmony_ci/* Decode a literal (one 8-bit byte) */ 17230f66f451Sopenharmony_cistatic void lzma_literal(struct xz_dec_lzma2 *s) 17240f66f451Sopenharmony_ci{ 17250f66f451Sopenharmony_ci uint16_t *probs; 17260f66f451Sopenharmony_ci uint32_t symbol; 17270f66f451Sopenharmony_ci uint32_t match_byte; 17280f66f451Sopenharmony_ci uint32_t match_bit; 17290f66f451Sopenharmony_ci uint32_t offset; 17300f66f451Sopenharmony_ci uint32_t i; 17310f66f451Sopenharmony_ci 17320f66f451Sopenharmony_ci probs = lzma_literal_probs(s); 17330f66f451Sopenharmony_ci 17340f66f451Sopenharmony_ci if (lzma_state_is_literal(s->lzma.state)) { 17350f66f451Sopenharmony_ci symbol = rc_bittree(&s->rc, probs, 0x100); 17360f66f451Sopenharmony_ci } else { 17370f66f451Sopenharmony_ci symbol = 1; 17380f66f451Sopenharmony_ci match_byte = dict_get(&s->dict, s->lzma.rep0) << 1; 17390f66f451Sopenharmony_ci offset = 0x100; 17400f66f451Sopenharmony_ci 17410f66f451Sopenharmony_ci do { 17420f66f451Sopenharmony_ci match_bit = match_byte & offset; 17430f66f451Sopenharmony_ci match_byte <<= 1; 17440f66f451Sopenharmony_ci i = offset + match_bit + symbol; 17450f66f451Sopenharmony_ci 17460f66f451Sopenharmony_ci if (rc_bit(&s->rc, &probs[i])) { 17470f66f451Sopenharmony_ci symbol = (symbol << 1) + 1; 17480f66f451Sopenharmony_ci offset &= match_bit; 17490f66f451Sopenharmony_ci } else { 17500f66f451Sopenharmony_ci symbol <<= 1; 17510f66f451Sopenharmony_ci offset &= ~match_bit; 17520f66f451Sopenharmony_ci } 17530f66f451Sopenharmony_ci } while (symbol < 0x100); 17540f66f451Sopenharmony_ci } 17550f66f451Sopenharmony_ci 17560f66f451Sopenharmony_ci dict_put(&s->dict, (uint8_t)symbol); 17570f66f451Sopenharmony_ci lzma_state_literal(&s->lzma.state); 17580f66f451Sopenharmony_ci} 17590f66f451Sopenharmony_ci 17600f66f451Sopenharmony_ci/* Decode the length of the match into s->lzma.len. */ 17610f66f451Sopenharmony_cistatic void lzma_len(struct xz_dec_lzma2 *s, struct lzma_len_dec *l, 17620f66f451Sopenharmony_ci uint32_t pos_state) 17630f66f451Sopenharmony_ci{ 17640f66f451Sopenharmony_ci uint16_t *probs; 17650f66f451Sopenharmony_ci uint32_t limit; 17660f66f451Sopenharmony_ci 17670f66f451Sopenharmony_ci if (!rc_bit(&s->rc, &l->choice)) { 17680f66f451Sopenharmony_ci probs = l->low[pos_state]; 17690f66f451Sopenharmony_ci limit = LEN_LOW_SYMBOLS; 17700f66f451Sopenharmony_ci s->lzma.len = MATCH_LEN_MIN; 17710f66f451Sopenharmony_ci } else { 17720f66f451Sopenharmony_ci if (!rc_bit(&s->rc, &l->choice2)) { 17730f66f451Sopenharmony_ci probs = l->mid[pos_state]; 17740f66f451Sopenharmony_ci limit = LEN_MID_SYMBOLS; 17750f66f451Sopenharmony_ci s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; 17760f66f451Sopenharmony_ci } else { 17770f66f451Sopenharmony_ci probs = l->high; 17780f66f451Sopenharmony_ci limit = LEN_HIGH_SYMBOLS; 17790f66f451Sopenharmony_ci s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS 17800f66f451Sopenharmony_ci + LEN_MID_SYMBOLS; 17810f66f451Sopenharmony_ci } 17820f66f451Sopenharmony_ci } 17830f66f451Sopenharmony_ci 17840f66f451Sopenharmony_ci s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit; 17850f66f451Sopenharmony_ci} 17860f66f451Sopenharmony_ci 17870f66f451Sopenharmony_ci/* Decode a match. The distance will be stored in s->lzma.rep0. */ 17880f66f451Sopenharmony_cistatic void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state) 17890f66f451Sopenharmony_ci{ 17900f66f451Sopenharmony_ci uint16_t *probs; 17910f66f451Sopenharmony_ci uint32_t dist_slot; 17920f66f451Sopenharmony_ci uint32_t limit; 17930f66f451Sopenharmony_ci 17940f66f451Sopenharmony_ci lzma_state_match(&s->lzma.state); 17950f66f451Sopenharmony_ci 17960f66f451Sopenharmony_ci s->lzma.rep3 = s->lzma.rep2; 17970f66f451Sopenharmony_ci s->lzma.rep2 = s->lzma.rep1; 17980f66f451Sopenharmony_ci s->lzma.rep1 = s->lzma.rep0; 17990f66f451Sopenharmony_ci 18000f66f451Sopenharmony_ci lzma_len(s, &s->lzma.match_len_dec, pos_state); 18010f66f451Sopenharmony_ci 18020f66f451Sopenharmony_ci probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)]; 18030f66f451Sopenharmony_ci dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS; 18040f66f451Sopenharmony_ci 18050f66f451Sopenharmony_ci if (dist_slot < DIST_MODEL_START) { 18060f66f451Sopenharmony_ci s->lzma.rep0 = dist_slot; 18070f66f451Sopenharmony_ci } else { 18080f66f451Sopenharmony_ci limit = (dist_slot >> 1) - 1; 18090f66f451Sopenharmony_ci s->lzma.rep0 = 2 + (dist_slot & 1); 18100f66f451Sopenharmony_ci 18110f66f451Sopenharmony_ci if (dist_slot < DIST_MODEL_END) { 18120f66f451Sopenharmony_ci s->lzma.rep0 <<= limit; 18130f66f451Sopenharmony_ci probs = s->lzma.dist_special + s->lzma.rep0 18140f66f451Sopenharmony_ci - dist_slot - 1; 18150f66f451Sopenharmony_ci rc_bittree_reverse(&s->rc, probs, 18160f66f451Sopenharmony_ci &s->lzma.rep0, limit); 18170f66f451Sopenharmony_ci } else { 18180f66f451Sopenharmony_ci rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS); 18190f66f451Sopenharmony_ci s->lzma.rep0 <<= ALIGN_BITS; 18200f66f451Sopenharmony_ci rc_bittree_reverse(&s->rc, s->lzma.dist_align, 18210f66f451Sopenharmony_ci &s->lzma.rep0, ALIGN_BITS); 18220f66f451Sopenharmony_ci } 18230f66f451Sopenharmony_ci } 18240f66f451Sopenharmony_ci} 18250f66f451Sopenharmony_ci 18260f66f451Sopenharmony_ci/* 18270f66f451Sopenharmony_ci * Decode a repeated match. The distance is one of the four most recently 18280f66f451Sopenharmony_ci * seen matches. The distance will be stored in s->lzma.rep0. 18290f66f451Sopenharmony_ci */ 18300f66f451Sopenharmony_cistatic void lzma_rep_match(struct xz_dec_lzma2 *s, uint32_t pos_state) 18310f66f451Sopenharmony_ci{ 18320f66f451Sopenharmony_ci uint32_t tmp; 18330f66f451Sopenharmony_ci 18340f66f451Sopenharmony_ci if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state])) { 18350f66f451Sopenharmony_ci if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[ 18360f66f451Sopenharmony_ci s->lzma.state][pos_state])) { 18370f66f451Sopenharmony_ci lzma_state_short_rep(&s->lzma.state); 18380f66f451Sopenharmony_ci s->lzma.len = 1; 18390f66f451Sopenharmony_ci return; 18400f66f451Sopenharmony_ci } 18410f66f451Sopenharmony_ci } else { 18420f66f451Sopenharmony_ci if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state])) { 18430f66f451Sopenharmony_ci tmp = s->lzma.rep1; 18440f66f451Sopenharmony_ci } else { 18450f66f451Sopenharmony_ci if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state])) { 18460f66f451Sopenharmony_ci tmp = s->lzma.rep2; 18470f66f451Sopenharmony_ci } else { 18480f66f451Sopenharmony_ci tmp = s->lzma.rep3; 18490f66f451Sopenharmony_ci s->lzma.rep3 = s->lzma.rep2; 18500f66f451Sopenharmony_ci } 18510f66f451Sopenharmony_ci 18520f66f451Sopenharmony_ci s->lzma.rep2 = s->lzma.rep1; 18530f66f451Sopenharmony_ci } 18540f66f451Sopenharmony_ci 18550f66f451Sopenharmony_ci s->lzma.rep1 = s->lzma.rep0; 18560f66f451Sopenharmony_ci s->lzma.rep0 = tmp; 18570f66f451Sopenharmony_ci } 18580f66f451Sopenharmony_ci 18590f66f451Sopenharmony_ci lzma_state_long_rep(&s->lzma.state); 18600f66f451Sopenharmony_ci lzma_len(s, &s->lzma.rep_len_dec, pos_state); 18610f66f451Sopenharmony_ci} 18620f66f451Sopenharmony_ci 18630f66f451Sopenharmony_ci/* LZMA decoder core */ 18640f66f451Sopenharmony_cistatic int lzma_main(struct xz_dec_lzma2 *s) 18650f66f451Sopenharmony_ci{ 18660f66f451Sopenharmony_ci uint32_t pos_state; 18670f66f451Sopenharmony_ci 18680f66f451Sopenharmony_ci /* 18690f66f451Sopenharmony_ci * If the dictionary was reached during the previous call, try to 18700f66f451Sopenharmony_ci * finish the possibly pending repeat in the dictionary. 18710f66f451Sopenharmony_ci */ 18720f66f451Sopenharmony_ci if (dict_has_space(&s->dict) && s->lzma.len > 0) 18730f66f451Sopenharmony_ci dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0); 18740f66f451Sopenharmony_ci 18750f66f451Sopenharmony_ci /* 18760f66f451Sopenharmony_ci * Decode more LZMA symbols. One iteration may consume up to 18770f66f451Sopenharmony_ci * LZMA_IN_REQUIRED - 1 bytes. 18780f66f451Sopenharmony_ci */ 18790f66f451Sopenharmony_ci while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc)) { 18800f66f451Sopenharmony_ci pos_state = s->dict.pos & s->lzma.pos_mask; 18810f66f451Sopenharmony_ci 18820f66f451Sopenharmony_ci if (!rc_bit(&s->rc, &s->lzma.is_match[ 18830f66f451Sopenharmony_ci s->lzma.state][pos_state])) { 18840f66f451Sopenharmony_ci lzma_literal(s); 18850f66f451Sopenharmony_ci } else { 18860f66f451Sopenharmony_ci if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state])) 18870f66f451Sopenharmony_ci lzma_rep_match(s, pos_state); 18880f66f451Sopenharmony_ci else 18890f66f451Sopenharmony_ci lzma_match(s, pos_state); 18900f66f451Sopenharmony_ci 18910f66f451Sopenharmony_ci if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0)) 18920f66f451Sopenharmony_ci return 0; 18930f66f451Sopenharmony_ci } 18940f66f451Sopenharmony_ci } 18950f66f451Sopenharmony_ci 18960f66f451Sopenharmony_ci /* 18970f66f451Sopenharmony_ci * Having the range decoder always normalized when we are outside 18980f66f451Sopenharmony_ci * this function makes it easier to correctly handle end of the chunk. 18990f66f451Sopenharmony_ci */ 19000f66f451Sopenharmony_ci rc_normalize(&s->rc); 19010f66f451Sopenharmony_ci 19020f66f451Sopenharmony_ci return 1; 19030f66f451Sopenharmony_ci} 19040f66f451Sopenharmony_ci 19050f66f451Sopenharmony_ci/* 19060f66f451Sopenharmony_ci * Reset the LZMA decoder and range decoder state. Dictionary is nore reset 19070f66f451Sopenharmony_ci * here, because LZMA state may be reset without resetting the dictionary. 19080f66f451Sopenharmony_ci */ 19090f66f451Sopenharmony_cistatic void lzma_reset(struct xz_dec_lzma2 *s) 19100f66f451Sopenharmony_ci{ 19110f66f451Sopenharmony_ci uint16_t *probs; 19120f66f451Sopenharmony_ci size_t i; 19130f66f451Sopenharmony_ci 19140f66f451Sopenharmony_ci s->lzma.state = STATE_LIT_LIT; 19150f66f451Sopenharmony_ci s->lzma.rep0 = 0; 19160f66f451Sopenharmony_ci s->lzma.rep1 = 0; 19170f66f451Sopenharmony_ci s->lzma.rep2 = 0; 19180f66f451Sopenharmony_ci s->lzma.rep3 = 0; 19190f66f451Sopenharmony_ci 19200f66f451Sopenharmony_ci /* 19210f66f451Sopenharmony_ci * All probabilities are initialized to the same value. This hack 19220f66f451Sopenharmony_ci * makes the code smaller by avoiding a separate loop for each 19230f66f451Sopenharmony_ci * probability array. 19240f66f451Sopenharmony_ci * 19250f66f451Sopenharmony_ci * This could be optimized so that only that part of literal 19260f66f451Sopenharmony_ci * probabilities that are actually required. In the common case 19270f66f451Sopenharmony_ci * we would write 12 KiB less. 19280f66f451Sopenharmony_ci */ 19290f66f451Sopenharmony_ci probs = s->lzma.is_match[0]; 19300f66f451Sopenharmony_ci for (i = 0; i < PROBS_TOTAL; ++i) 19310f66f451Sopenharmony_ci probs[i] = RC_BIT_MODEL_TOTAL / 2; 19320f66f451Sopenharmony_ci 19330f66f451Sopenharmony_ci rc_reset(&s->rc); 19340f66f451Sopenharmony_ci} 19350f66f451Sopenharmony_ci 19360f66f451Sopenharmony_ci/* 19370f66f451Sopenharmony_ci * Decode and validate LZMA properties (lc/lp/pb) and calculate the bit masks 19380f66f451Sopenharmony_ci * from the decoded lp and pb values. On success, the LZMA decoder state is 19390f66f451Sopenharmony_ci * reset and true is returned. 19400f66f451Sopenharmony_ci */ 19410f66f451Sopenharmony_cistatic int lzma_props(struct xz_dec_lzma2 *s, uint8_t props) 19420f66f451Sopenharmony_ci{ 19430f66f451Sopenharmony_ci if (props > (4 * 5 + 4) * 9 + 8) 19440f66f451Sopenharmony_ci return 0; 19450f66f451Sopenharmony_ci 19460f66f451Sopenharmony_ci s->lzma.pos_mask = 0; 19470f66f451Sopenharmony_ci while (props >= 9 * 5) { 19480f66f451Sopenharmony_ci props -= 9 * 5; 19490f66f451Sopenharmony_ci ++s->lzma.pos_mask; 19500f66f451Sopenharmony_ci } 19510f66f451Sopenharmony_ci 19520f66f451Sopenharmony_ci s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1; 19530f66f451Sopenharmony_ci 19540f66f451Sopenharmony_ci s->lzma.literal_pos_mask = 0; 19550f66f451Sopenharmony_ci while (props >= 9) { 19560f66f451Sopenharmony_ci props -= 9; 19570f66f451Sopenharmony_ci ++s->lzma.literal_pos_mask; 19580f66f451Sopenharmony_ci } 19590f66f451Sopenharmony_ci 19600f66f451Sopenharmony_ci s->lzma.lc = props; 19610f66f451Sopenharmony_ci 19620f66f451Sopenharmony_ci if (s->lzma.lc + s->lzma.literal_pos_mask > 4) 19630f66f451Sopenharmony_ci return 0; 19640f66f451Sopenharmony_ci 19650f66f451Sopenharmony_ci s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1; 19660f66f451Sopenharmony_ci 19670f66f451Sopenharmony_ci lzma_reset(s); 19680f66f451Sopenharmony_ci 19690f66f451Sopenharmony_ci return 1; 19700f66f451Sopenharmony_ci} 19710f66f451Sopenharmony_ci 19720f66f451Sopenharmony_ci/********* 19730f66f451Sopenharmony_ci * LZMA2 * 19740f66f451Sopenharmony_ci *********/ 19750f66f451Sopenharmony_ci 19760f66f451Sopenharmony_ci/* 19770f66f451Sopenharmony_ci * The LZMA decoder assumes that if the input limit (s->rc.in_limit) hasn't 19780f66f451Sopenharmony_ci * been exceeded, it is safe to read up to LZMA_IN_REQUIRED bytes. This 19790f66f451Sopenharmony_ci * wrapper function takes care of making the LZMA decoder's assumption safe. 19800f66f451Sopenharmony_ci * 19810f66f451Sopenharmony_ci * As long as there is plenty of input left to be decoded in the current LZMA 19820f66f451Sopenharmony_ci * chunk, we decode directly from the caller-supplied input buffer until 19830f66f451Sopenharmony_ci * there's LZMA_IN_REQUIRED bytes left. Those remaining bytes are copied into 19840f66f451Sopenharmony_ci * s->temp.buf, which (hopefully) gets filled on the next call to this 19850f66f451Sopenharmony_ci * function. We decode a few bytes from the temporary buffer so that we can 19860f66f451Sopenharmony_ci * continue decoding from the caller-supplied input buffer again. 19870f66f451Sopenharmony_ci */ 19880f66f451Sopenharmony_cistatic int lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b) 19890f66f451Sopenharmony_ci{ 19900f66f451Sopenharmony_ci size_t in_avail; 19910f66f451Sopenharmony_ci uint32_t tmp; 19920f66f451Sopenharmony_ci 19930f66f451Sopenharmony_ci in_avail = b->in_size - b->in_pos; 19940f66f451Sopenharmony_ci if (s->temp.size > 0 || s->lzma2.compressed == 0) { 19950f66f451Sopenharmony_ci tmp = 2 * LZMA_IN_REQUIRED - s->temp.size; 19960f66f451Sopenharmony_ci if (tmp > s->lzma2.compressed - s->temp.size) 19970f66f451Sopenharmony_ci tmp = s->lzma2.compressed - s->temp.size; 19980f66f451Sopenharmony_ci if (tmp > in_avail) 19990f66f451Sopenharmony_ci tmp = in_avail; 20000f66f451Sopenharmony_ci 20010f66f451Sopenharmony_ci memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp); 20020f66f451Sopenharmony_ci 20030f66f451Sopenharmony_ci if (s->temp.size + tmp == s->lzma2.compressed) { 20040f66f451Sopenharmony_ci memset(s->temp.buf + s->temp.size + tmp, 0, 20050f66f451Sopenharmony_ci sizeof(s->temp.buf) 20060f66f451Sopenharmony_ci - s->temp.size - tmp); 20070f66f451Sopenharmony_ci s->rc.in_limit = s->temp.size + tmp; 20080f66f451Sopenharmony_ci } else if (s->temp.size + tmp < LZMA_IN_REQUIRED) { 20090f66f451Sopenharmony_ci s->temp.size += tmp; 20100f66f451Sopenharmony_ci b->in_pos += tmp; 20110f66f451Sopenharmony_ci return 1; 20120f66f451Sopenharmony_ci } else { 20130f66f451Sopenharmony_ci s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED; 20140f66f451Sopenharmony_ci } 20150f66f451Sopenharmony_ci 20160f66f451Sopenharmony_ci s->rc.in = s->temp.buf; 20170f66f451Sopenharmony_ci s->rc.in_pos = 0; 20180f66f451Sopenharmony_ci 20190f66f451Sopenharmony_ci if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp) 20200f66f451Sopenharmony_ci return 0; 20210f66f451Sopenharmony_ci 20220f66f451Sopenharmony_ci s->lzma2.compressed -= s->rc.in_pos; 20230f66f451Sopenharmony_ci 20240f66f451Sopenharmony_ci if (s->rc.in_pos < s->temp.size) { 20250f66f451Sopenharmony_ci s->temp.size -= s->rc.in_pos; 20260f66f451Sopenharmony_ci memmove(s->temp.buf, s->temp.buf + s->rc.in_pos, 20270f66f451Sopenharmony_ci s->temp.size); 20280f66f451Sopenharmony_ci return 1; 20290f66f451Sopenharmony_ci } 20300f66f451Sopenharmony_ci 20310f66f451Sopenharmony_ci b->in_pos += s->rc.in_pos - s->temp.size; 20320f66f451Sopenharmony_ci s->temp.size = 0; 20330f66f451Sopenharmony_ci } 20340f66f451Sopenharmony_ci 20350f66f451Sopenharmony_ci in_avail = b->in_size - b->in_pos; 20360f66f451Sopenharmony_ci if (in_avail >= LZMA_IN_REQUIRED) { 20370f66f451Sopenharmony_ci s->rc.in = b->in; 20380f66f451Sopenharmony_ci s->rc.in_pos = b->in_pos; 20390f66f451Sopenharmony_ci 20400f66f451Sopenharmony_ci if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED) 20410f66f451Sopenharmony_ci s->rc.in_limit = b->in_pos + s->lzma2.compressed; 20420f66f451Sopenharmony_ci else 20430f66f451Sopenharmony_ci s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED; 20440f66f451Sopenharmony_ci 20450f66f451Sopenharmony_ci if (!lzma_main(s)) 20460f66f451Sopenharmony_ci return 0; 20470f66f451Sopenharmony_ci 20480f66f451Sopenharmony_ci in_avail = s->rc.in_pos - b->in_pos; 20490f66f451Sopenharmony_ci if (in_avail > s->lzma2.compressed) return 0; 20500f66f451Sopenharmony_ci 20510f66f451Sopenharmony_ci s->lzma2.compressed -= in_avail; 20520f66f451Sopenharmony_ci b->in_pos = s->rc.in_pos; 20530f66f451Sopenharmony_ci } 20540f66f451Sopenharmony_ci 20550f66f451Sopenharmony_ci in_avail = b->in_size - b->in_pos; 20560f66f451Sopenharmony_ci if (in_avail < LZMA_IN_REQUIRED) { 20570f66f451Sopenharmony_ci if (in_avail > s->lzma2.compressed) 20580f66f451Sopenharmony_ci in_avail = s->lzma2.compressed; 20590f66f451Sopenharmony_ci 20600f66f451Sopenharmony_ci memcpy(s->temp.buf, b->in + b->in_pos, in_avail); 20610f66f451Sopenharmony_ci s->temp.size = in_avail; 20620f66f451Sopenharmony_ci b->in_pos += in_avail; 20630f66f451Sopenharmony_ci } 20640f66f451Sopenharmony_ci 20650f66f451Sopenharmony_ci return 1; 20660f66f451Sopenharmony_ci} 20670f66f451Sopenharmony_ci 20680f66f451Sopenharmony_ci/* 20690f66f451Sopenharmony_ci * Take care of the LZMA2 control layer, and forward the job of actual LZMA 20700f66f451Sopenharmony_ci * decoding or copying of uncompressed chunks to other functions. 20710f66f451Sopenharmony_ci */ 20720f66f451Sopenharmony_cienum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, 20730f66f451Sopenharmony_ci struct xz_buf *b) 20740f66f451Sopenharmony_ci{ 20750f66f451Sopenharmony_ci uint32_t tmp; 20760f66f451Sopenharmony_ci 20770f66f451Sopenharmony_ci while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN) { 20780f66f451Sopenharmony_ci switch (s->lzma2.sequence) { 20790f66f451Sopenharmony_ci case SEQ_CONTROL: 20800f66f451Sopenharmony_ci /* 20810f66f451Sopenharmony_ci * LZMA2 control byte 20820f66f451Sopenharmony_ci * 20830f66f451Sopenharmony_ci * Exact values: 20840f66f451Sopenharmony_ci * 0x00 End marker 20850f66f451Sopenharmony_ci * 0x01 Dictionary reset followed by 20860f66f451Sopenharmony_ci * an uncompressed chunk 20870f66f451Sopenharmony_ci * 0x02 Uncompressed chunk (no dictionary reset) 20880f66f451Sopenharmony_ci * 20890f66f451Sopenharmony_ci * Highest three bits (s->control & 0xE0): 20900f66f451Sopenharmony_ci * 0xE0 Dictionary reset, new properties and state 20910f66f451Sopenharmony_ci * reset, followed by LZMA compressed chunk 20920f66f451Sopenharmony_ci * 0xC0 New properties and state reset, followed 20930f66f451Sopenharmony_ci * by LZMA compressed chunk (no dictionary 20940f66f451Sopenharmony_ci * reset) 20950f66f451Sopenharmony_ci * 0xA0 State reset using old properties, 20960f66f451Sopenharmony_ci * followed by LZMA compressed chunk (no 20970f66f451Sopenharmony_ci * dictionary reset) 20980f66f451Sopenharmony_ci * 0x80 LZMA chunk (no dictionary or state reset) 20990f66f451Sopenharmony_ci * 21000f66f451Sopenharmony_ci * For LZMA compressed chunks, the lowest five bits 21010f66f451Sopenharmony_ci * (s->control & 1F) are the highest bits of the 21020f66f451Sopenharmony_ci * uncompressed size (bits 16-20). 21030f66f451Sopenharmony_ci * 21040f66f451Sopenharmony_ci * A new LZMA2 stream must begin with a dictionary 21050f66f451Sopenharmony_ci * reset. The first LZMA chunk must set new 21060f66f451Sopenharmony_ci * properties and reset the LZMA state. 21070f66f451Sopenharmony_ci * 21080f66f451Sopenharmony_ci * Values that don't match anything described above 21090f66f451Sopenharmony_ci * are invalid and we return XZ_DATA_ERROR. 21100f66f451Sopenharmony_ci */ 21110f66f451Sopenharmony_ci tmp = b->in[b->in_pos++]; 21120f66f451Sopenharmony_ci 21130f66f451Sopenharmony_ci if (tmp == 0x00) 21140f66f451Sopenharmony_ci return XZ_STREAM_END; 21150f66f451Sopenharmony_ci 21160f66f451Sopenharmony_ci if (tmp >= 0xE0 || tmp == 0x01) { 21170f66f451Sopenharmony_ci s->lzma2.need_props = 1; 21180f66f451Sopenharmony_ci s->lzma2.need_dict_reset = 0; 21190f66f451Sopenharmony_ci dict_reset(&s->dict); 21200f66f451Sopenharmony_ci } else if (s->lzma2.need_dict_reset) { 21210f66f451Sopenharmony_ci return XZ_DATA_ERROR; 21220f66f451Sopenharmony_ci } 21230f66f451Sopenharmony_ci 21240f66f451Sopenharmony_ci if (tmp >= 0x80) { 21250f66f451Sopenharmony_ci s->lzma2.uncompressed = (tmp & 0x1F) << 16; 21260f66f451Sopenharmony_ci s->lzma2.sequence = SEQ_UNCOMPRESSED_1; 21270f66f451Sopenharmony_ci 21280f66f451Sopenharmony_ci if (tmp >= 0xC0) { 21290f66f451Sopenharmony_ci /* 21300f66f451Sopenharmony_ci * When there are new properties, 21310f66f451Sopenharmony_ci * state reset is done at 21320f66f451Sopenharmony_ci * SEQ_PROPERTIES. 21330f66f451Sopenharmony_ci */ 21340f66f451Sopenharmony_ci s->lzma2.need_props = 0; 21350f66f451Sopenharmony_ci s->lzma2.next_sequence 21360f66f451Sopenharmony_ci = SEQ_PROPERTIES; 21370f66f451Sopenharmony_ci 21380f66f451Sopenharmony_ci } else if (s->lzma2.need_props) { 21390f66f451Sopenharmony_ci return XZ_DATA_ERROR; 21400f66f451Sopenharmony_ci 21410f66f451Sopenharmony_ci } else { 21420f66f451Sopenharmony_ci s->lzma2.next_sequence 21430f66f451Sopenharmony_ci = SEQ_LZMA_PREPARE; 21440f66f451Sopenharmony_ci if (tmp >= 0xA0) 21450f66f451Sopenharmony_ci lzma_reset(s); 21460f66f451Sopenharmony_ci } 21470f66f451Sopenharmony_ci } else { 21480f66f451Sopenharmony_ci if (tmp > 0x02) 21490f66f451Sopenharmony_ci return XZ_DATA_ERROR; 21500f66f451Sopenharmony_ci 21510f66f451Sopenharmony_ci s->lzma2.sequence = SEQ_COMPRESSED_0; 21520f66f451Sopenharmony_ci s->lzma2.next_sequence = SEQ_COPY; 21530f66f451Sopenharmony_ci } 21540f66f451Sopenharmony_ci 21550f66f451Sopenharmony_ci break; 21560f66f451Sopenharmony_ci 21570f66f451Sopenharmony_ci case SEQ_UNCOMPRESSED_1: 21580f66f451Sopenharmony_ci s->lzma2.uncompressed 21590f66f451Sopenharmony_ci += (uint32_t)b->in[b->in_pos++] << 8; 21600f66f451Sopenharmony_ci s->lzma2.sequence = SEQ_UNCOMPRESSED_2; 21610f66f451Sopenharmony_ci break; 21620f66f451Sopenharmony_ci 21630f66f451Sopenharmony_ci case SEQ_UNCOMPRESSED_2: 21640f66f451Sopenharmony_ci s->lzma2.uncompressed 21650f66f451Sopenharmony_ci += (uint32_t)b->in[b->in_pos++] + 1; 21660f66f451Sopenharmony_ci s->lzma2.sequence = SEQ_COMPRESSED_0; 21670f66f451Sopenharmony_ci break; 21680f66f451Sopenharmony_ci 21690f66f451Sopenharmony_ci case SEQ_COMPRESSED_0: 21700f66f451Sopenharmony_ci s->lzma2.compressed 21710f66f451Sopenharmony_ci = (uint32_t)b->in[b->in_pos++] << 8; 21720f66f451Sopenharmony_ci s->lzma2.sequence = SEQ_COMPRESSED_1; 21730f66f451Sopenharmony_ci break; 21740f66f451Sopenharmony_ci 21750f66f451Sopenharmony_ci case SEQ_COMPRESSED_1: 21760f66f451Sopenharmony_ci s->lzma2.compressed 21770f66f451Sopenharmony_ci += (uint32_t)b->in[b->in_pos++] + 1; 21780f66f451Sopenharmony_ci s->lzma2.sequence = s->lzma2.next_sequence; 21790f66f451Sopenharmony_ci break; 21800f66f451Sopenharmony_ci 21810f66f451Sopenharmony_ci case SEQ_PROPERTIES: 21820f66f451Sopenharmony_ci if (!lzma_props(s, b->in[b->in_pos++])) 21830f66f451Sopenharmony_ci return XZ_DATA_ERROR; 21840f66f451Sopenharmony_ci 21850f66f451Sopenharmony_ci s->lzma2.sequence = SEQ_LZMA_PREPARE; 21860f66f451Sopenharmony_ci 21870f66f451Sopenharmony_ci case SEQ_LZMA_PREPARE: 21880f66f451Sopenharmony_ci if (s->lzma2.compressed < RC_INIT_BYTES) 21890f66f451Sopenharmony_ci return XZ_DATA_ERROR; 21900f66f451Sopenharmony_ci 21910f66f451Sopenharmony_ci if (!rc_read_init(&s->rc, b)) 21920f66f451Sopenharmony_ci return XZ_OK; 21930f66f451Sopenharmony_ci 21940f66f451Sopenharmony_ci s->lzma2.compressed -= RC_INIT_BYTES; 21950f66f451Sopenharmony_ci s->lzma2.sequence = SEQ_LZMA_RUN; 21960f66f451Sopenharmony_ci 21970f66f451Sopenharmony_ci case SEQ_LZMA_RUN: 21980f66f451Sopenharmony_ci /* 21990f66f451Sopenharmony_ci * Set dictionary limit to indicate how much we want 22000f66f451Sopenharmony_ci * to be encoded at maximum. Decode new data into the 22010f66f451Sopenharmony_ci * dictionary. Flush the new data from dictionary to 22020f66f451Sopenharmony_ci * b->out. Check if we finished decoding this chunk. 22030f66f451Sopenharmony_ci * In case the dictionary got full but we didn't fill 22040f66f451Sopenharmony_ci * the output buffer yet, we may run this loop 22050f66f451Sopenharmony_ci * multiple times without changing s->lzma2.sequence. 22060f66f451Sopenharmony_ci */ 22070f66f451Sopenharmony_ci dict_limit(&s->dict, minof(b->out_size - b->out_pos, 22080f66f451Sopenharmony_ci s->lzma2.uncompressed)); 22090f66f451Sopenharmony_ci if (!lzma2_lzma(s, b)) 22100f66f451Sopenharmony_ci return XZ_DATA_ERROR; 22110f66f451Sopenharmony_ci 22120f66f451Sopenharmony_ci s->lzma2.uncompressed -= dict_flush(&s->dict, b); 22130f66f451Sopenharmony_ci 22140f66f451Sopenharmony_ci if (s->lzma2.uncompressed == 0) { 22150f66f451Sopenharmony_ci if (s->lzma2.compressed > 0 || s->lzma.len > 0 22160f66f451Sopenharmony_ci || !rc_is_finished(&s->rc)) 22170f66f451Sopenharmony_ci return XZ_DATA_ERROR; 22180f66f451Sopenharmony_ci 22190f66f451Sopenharmony_ci rc_reset(&s->rc); 22200f66f451Sopenharmony_ci s->lzma2.sequence = SEQ_CONTROL; 22210f66f451Sopenharmony_ci 22220f66f451Sopenharmony_ci } else if (b->out_pos == b->out_size 22230f66f451Sopenharmony_ci || (b->in_pos == b->in_size 22240f66f451Sopenharmony_ci && s->temp.size 22250f66f451Sopenharmony_ci < s->lzma2.compressed)) { 22260f66f451Sopenharmony_ci return XZ_OK; 22270f66f451Sopenharmony_ci } 22280f66f451Sopenharmony_ci 22290f66f451Sopenharmony_ci break; 22300f66f451Sopenharmony_ci 22310f66f451Sopenharmony_ci case SEQ_COPY: 22320f66f451Sopenharmony_ci dict_uncompressed(&s->dict, b, &s->lzma2.compressed); 22330f66f451Sopenharmony_ci if (s->lzma2.compressed > 0) 22340f66f451Sopenharmony_ci return XZ_OK; 22350f66f451Sopenharmony_ci 22360f66f451Sopenharmony_ci s->lzma2.sequence = SEQ_CONTROL; 22370f66f451Sopenharmony_ci break; 22380f66f451Sopenharmony_ci } 22390f66f451Sopenharmony_ci } 22400f66f451Sopenharmony_ci 22410f66f451Sopenharmony_ci return XZ_OK; 22420f66f451Sopenharmony_ci} 22430f66f451Sopenharmony_ci 22440f66f451Sopenharmony_cistruct xz_dec_lzma2 *xz_dec_lzma2_create(uint32_t dict_max) 22450f66f451Sopenharmony_ci{ 22460f66f451Sopenharmony_ci struct xz_dec_lzma2 *s = malloc(sizeof(*s)); 22470f66f451Sopenharmony_ci if (s == NULL) 22480f66f451Sopenharmony_ci return NULL; 22490f66f451Sopenharmony_ci 22500f66f451Sopenharmony_ci s->dict.size_max = dict_max; 22510f66f451Sopenharmony_ci s->dict.buf = NULL; 22520f66f451Sopenharmony_ci s->dict.allocated = 0; 22530f66f451Sopenharmony_ci 22540f66f451Sopenharmony_ci return s; 22550f66f451Sopenharmony_ci} 22560f66f451Sopenharmony_ci 22570f66f451Sopenharmony_cienum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props) 22580f66f451Sopenharmony_ci{ 22590f66f451Sopenharmony_ci /* This limits dictionary size to 3 GiB to keep parsing simpler. */ 22600f66f451Sopenharmony_ci if (props > 39) 22610f66f451Sopenharmony_ci return XZ_OPTIONS_ERROR; 22620f66f451Sopenharmony_ci 22630f66f451Sopenharmony_ci s->dict.size = 2 + (props & 1); 22640f66f451Sopenharmony_ci s->dict.size <<= (props >> 1) + 11; 22650f66f451Sopenharmony_ci 22660f66f451Sopenharmony_ci if (s->dict.size > s->dict.size_max) 22670f66f451Sopenharmony_ci return XZ_MEMLIMIT_ERROR; 22680f66f451Sopenharmony_ci 22690f66f451Sopenharmony_ci s->dict.end = s->dict.size; 22700f66f451Sopenharmony_ci 22710f66f451Sopenharmony_ci if (s->dict.allocated < s->dict.size) { 22720f66f451Sopenharmony_ci free(s->dict.buf); 22730f66f451Sopenharmony_ci s->dict.buf = malloc(s->dict.size); 22740f66f451Sopenharmony_ci if (s->dict.buf == NULL) { 22750f66f451Sopenharmony_ci s->dict.allocated = 0; 22760f66f451Sopenharmony_ci return XZ_MEM_ERROR; 22770f66f451Sopenharmony_ci } 22780f66f451Sopenharmony_ci } 22790f66f451Sopenharmony_ci 22800f66f451Sopenharmony_ci s->lzma.len = 0; 22810f66f451Sopenharmony_ci 22820f66f451Sopenharmony_ci s->lzma2.sequence = SEQ_CONTROL; 22830f66f451Sopenharmony_ci s->lzma2.need_dict_reset = 1; 22840f66f451Sopenharmony_ci 22850f66f451Sopenharmony_ci s->temp.size = 0; 22860f66f451Sopenharmony_ci 22870f66f451Sopenharmony_ci return XZ_OK; 22880f66f451Sopenharmony_ci} 22890f66f451Sopenharmony_ci 22900f66f451Sopenharmony_ci/* 22910f66f451Sopenharmony_ci * .xz Stream decoder 22920f66f451Sopenharmony_ci */ 22930f66f451Sopenharmony_ci 22940f66f451Sopenharmony_ci 22950f66f451Sopenharmony_ci// BEGIN xz_stream.h 22960f66f451Sopenharmony_ci/* 22970f66f451Sopenharmony_ci * Definitions for handling the .xz file format 22980f66f451Sopenharmony_ci */ 22990f66f451Sopenharmony_ci 23000f66f451Sopenharmony_ci/* 23010f66f451Sopenharmony_ci * See the .xz file format specification at 23020f66f451Sopenharmony_ci * http://tukaani.org/xz/xz-file-format.txt 23030f66f451Sopenharmony_ci * to understand the container format. 23040f66f451Sopenharmony_ci */ 23050f66f451Sopenharmony_ci 23060f66f451Sopenharmony_ci#define STREAM_HEADER_SIZE 12 23070f66f451Sopenharmony_ci 23080f66f451Sopenharmony_ci#define HEADER_MAGIC "\3757zXZ" 23090f66f451Sopenharmony_ci#define HEADER_MAGIC_SIZE 6 23100f66f451Sopenharmony_ci 23110f66f451Sopenharmony_ci#define FOOTER_MAGIC "YZ" 23120f66f451Sopenharmony_ci#define FOOTER_MAGIC_SIZE 2 23130f66f451Sopenharmony_ci 23140f66f451Sopenharmony_ci/* 23150f66f451Sopenharmony_ci * Variable-length integer can hold a 63-bit unsigned integer or a special 23160f66f451Sopenharmony_ci * value indicating that the value is unknown. 23170f66f451Sopenharmony_ci * 23180f66f451Sopenharmony_ci * Experimental: vli_type can be defined to uint32_t to save a few bytes 23190f66f451Sopenharmony_ci * in code size (no effect on speed). Doing so limits the uncompressed and 23200f66f451Sopenharmony_ci * compressed size of the file to less than 256 MiB and may also weaken 23210f66f451Sopenharmony_ci * error detection slightly. 23220f66f451Sopenharmony_ci */ 23230f66f451Sopenharmony_citypedef uint64_t vli_type; 23240f66f451Sopenharmony_ci 23250f66f451Sopenharmony_ci#define VLI_MAX ((vli_type)-1 / 2) 23260f66f451Sopenharmony_ci#define VLI_UNKNOWN ((vli_type)-1) 23270f66f451Sopenharmony_ci 23280f66f451Sopenharmony_ci/* Maximum encoded size of a VLI */ 23290f66f451Sopenharmony_ci#define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7) 23300f66f451Sopenharmony_ci 23310f66f451Sopenharmony_ci/* Integrity Check types */ 23320f66f451Sopenharmony_cienum xz_check { 23330f66f451Sopenharmony_ci XZ_CHECK_NONE = 0, 23340f66f451Sopenharmony_ci XZ_CHECK_CRC32 = 1, 23350f66f451Sopenharmony_ci XZ_CHECK_CRC64 = 4, 23360f66f451Sopenharmony_ci XZ_CHECK_SHA256 = 10 23370f66f451Sopenharmony_ci}; 23380f66f451Sopenharmony_ci 23390f66f451Sopenharmony_ci/* Maximum possible Check ID */ 23400f66f451Sopenharmony_ci#define XZ_CHECK_MAX 15 23410f66f451Sopenharmony_ci// END xz_stream.h 23420f66f451Sopenharmony_ci 23430f66f451Sopenharmony_ci#define IS_CRC64(check_type) ((check_type) == XZ_CHECK_CRC64) 23440f66f451Sopenharmony_ci 23450f66f451Sopenharmony_ci/* Hash used to validate the Index field */ 23460f66f451Sopenharmony_cistruct xz_dec_hash { 23470f66f451Sopenharmony_ci vli_type unpadded; 23480f66f451Sopenharmony_ci vli_type uncompressed; 23490f66f451Sopenharmony_ci uint32_t crc32; 23500f66f451Sopenharmony_ci}; 23510f66f451Sopenharmony_ci 23520f66f451Sopenharmony_cistruct xz_dec { 23530f66f451Sopenharmony_ci /* Position in dec_main() */ 23540f66f451Sopenharmony_ci enum { 23550f66f451Sopenharmony_ci SEQ_STREAM_HEADER, 23560f66f451Sopenharmony_ci SEQ_BLOCK_START, 23570f66f451Sopenharmony_ci SEQ_BLOCK_HEADER, 23580f66f451Sopenharmony_ci SEQ_BLOCK_UNCOMPRESS, 23590f66f451Sopenharmony_ci SEQ_BLOCK_PADDING, 23600f66f451Sopenharmony_ci SEQ_BLOCK_CHECK, 23610f66f451Sopenharmony_ci SEQ_INDEX, 23620f66f451Sopenharmony_ci SEQ_INDEX_PADDING, 23630f66f451Sopenharmony_ci SEQ_INDEX_CRC32, 23640f66f451Sopenharmony_ci SEQ_STREAM_FOOTER 23650f66f451Sopenharmony_ci } sequence; 23660f66f451Sopenharmony_ci 23670f66f451Sopenharmony_ci /* Position in variable-length integers and Check fields */ 23680f66f451Sopenharmony_ci uint32_t pos; 23690f66f451Sopenharmony_ci 23700f66f451Sopenharmony_ci /* Variable-length integer decoded by dec_vli() */ 23710f66f451Sopenharmony_ci vli_type vli; 23720f66f451Sopenharmony_ci 23730f66f451Sopenharmony_ci /* Saved in_pos and out_pos */ 23740f66f451Sopenharmony_ci size_t in_start; 23750f66f451Sopenharmony_ci size_t out_start; 23760f66f451Sopenharmony_ci 23770f66f451Sopenharmony_ci /* CRC32 or CRC64 value in Block or CRC32 value in Index */ 23780f66f451Sopenharmony_ci uint64_t crc; 23790f66f451Sopenharmony_ci 23800f66f451Sopenharmony_ci /* Type of the integrity check calculated from uncompressed data */ 23810f66f451Sopenharmony_ci enum xz_check check_type; 23820f66f451Sopenharmony_ci 23830f66f451Sopenharmony_ci /* 23840f66f451Sopenharmony_ci * True if the next call to xz_dec_run() is allowed to return 23850f66f451Sopenharmony_ci * XZ_BUF_ERROR. 23860f66f451Sopenharmony_ci */ 23870f66f451Sopenharmony_ci int allow_buf_error; 23880f66f451Sopenharmony_ci 23890f66f451Sopenharmony_ci /* Information stored in Block Header */ 23900f66f451Sopenharmony_ci struct { 23910f66f451Sopenharmony_ci /* 23920f66f451Sopenharmony_ci * Value stored in the Compressed Size field, or 23930f66f451Sopenharmony_ci * VLI_UNKNOWN if Compressed Size is not present. 23940f66f451Sopenharmony_ci */ 23950f66f451Sopenharmony_ci vli_type compressed; 23960f66f451Sopenharmony_ci 23970f66f451Sopenharmony_ci /* 23980f66f451Sopenharmony_ci * Value stored in the Uncompressed Size field, or 23990f66f451Sopenharmony_ci * VLI_UNKNOWN if Uncompressed Size is not present. 24000f66f451Sopenharmony_ci */ 24010f66f451Sopenharmony_ci vli_type uncompressed; 24020f66f451Sopenharmony_ci 24030f66f451Sopenharmony_ci /* Size of the Block Header field */ 24040f66f451Sopenharmony_ci uint32_t size; 24050f66f451Sopenharmony_ci } block_header; 24060f66f451Sopenharmony_ci 24070f66f451Sopenharmony_ci /* Information collected when decoding Blocks */ 24080f66f451Sopenharmony_ci struct { 24090f66f451Sopenharmony_ci /* Observed compressed size of the current Block */ 24100f66f451Sopenharmony_ci vli_type compressed; 24110f66f451Sopenharmony_ci 24120f66f451Sopenharmony_ci /* Observed uncompressed size of the current Block */ 24130f66f451Sopenharmony_ci vli_type uncompressed; 24140f66f451Sopenharmony_ci 24150f66f451Sopenharmony_ci /* Number of Blocks decoded so far */ 24160f66f451Sopenharmony_ci vli_type count; 24170f66f451Sopenharmony_ci 24180f66f451Sopenharmony_ci /* 24190f66f451Sopenharmony_ci * Hash calculated from the Block sizes. This is used to 24200f66f451Sopenharmony_ci * validate the Index field. 24210f66f451Sopenharmony_ci */ 24220f66f451Sopenharmony_ci struct xz_dec_hash hash; 24230f66f451Sopenharmony_ci } block; 24240f66f451Sopenharmony_ci 24250f66f451Sopenharmony_ci /* Variables needed when verifying the Index field */ 24260f66f451Sopenharmony_ci struct { 24270f66f451Sopenharmony_ci /* Position in dec_index() */ 24280f66f451Sopenharmony_ci enum { 24290f66f451Sopenharmony_ci SEQ_INDEX_COUNT, 24300f66f451Sopenharmony_ci SEQ_INDEX_UNPADDED, 24310f66f451Sopenharmony_ci SEQ_INDEX_UNCOMPRESSED 24320f66f451Sopenharmony_ci } sequence; 24330f66f451Sopenharmony_ci 24340f66f451Sopenharmony_ci /* Size of the Index in bytes */ 24350f66f451Sopenharmony_ci vli_type size; 24360f66f451Sopenharmony_ci 24370f66f451Sopenharmony_ci /* Number of Records (matches block.count in valid files) */ 24380f66f451Sopenharmony_ci vli_type count; 24390f66f451Sopenharmony_ci 24400f66f451Sopenharmony_ci /* 24410f66f451Sopenharmony_ci * Hash calculated from the Records (matches block.hash in 24420f66f451Sopenharmony_ci * valid files). 24430f66f451Sopenharmony_ci */ 24440f66f451Sopenharmony_ci struct xz_dec_hash hash; 24450f66f451Sopenharmony_ci } index; 24460f66f451Sopenharmony_ci 24470f66f451Sopenharmony_ci /* 24480f66f451Sopenharmony_ci * Temporary buffer needed to hold Stream Header, Block Header, 24490f66f451Sopenharmony_ci * and Stream Footer. The Block Header is the biggest (1 KiB) 24500f66f451Sopenharmony_ci * so we reserve space according to that. buf[] has to be aligned 24510f66f451Sopenharmony_ci * to a multiple of four bytes; the size_t variables before it 24520f66f451Sopenharmony_ci * should guarantee this. 24530f66f451Sopenharmony_ci */ 24540f66f451Sopenharmony_ci struct { 24550f66f451Sopenharmony_ci size_t pos; 24560f66f451Sopenharmony_ci size_t size; 24570f66f451Sopenharmony_ci uint8_t buf[1024]; 24580f66f451Sopenharmony_ci } temp; 24590f66f451Sopenharmony_ci 24600f66f451Sopenharmony_ci struct xz_dec_lzma2 *lzma2; 24610f66f451Sopenharmony_ci 24620f66f451Sopenharmony_ci#ifdef XZ_DEC_BCJ 24630f66f451Sopenharmony_ci struct xz_dec_bcj *bcj; 24640f66f451Sopenharmony_ci int bcj_active; 24650f66f451Sopenharmony_ci#endif 24660f66f451Sopenharmony_ci}; 24670f66f451Sopenharmony_ci 24680f66f451Sopenharmony_ci/* Sizes of the Check field with different Check IDs */ 24690f66f451Sopenharmony_cistatic const uint8_t check_sizes[16] = { 24700f66f451Sopenharmony_ci 0, 24710f66f451Sopenharmony_ci 4, 4, 4, 24720f66f451Sopenharmony_ci 8, 8, 8, 24730f66f451Sopenharmony_ci 16, 16, 16, 24740f66f451Sopenharmony_ci 32, 32, 32, 24750f66f451Sopenharmony_ci 64, 64, 64 24760f66f451Sopenharmony_ci}; 24770f66f451Sopenharmony_ci 24780f66f451Sopenharmony_ci/* 24790f66f451Sopenharmony_ci * Fill s->temp by copying data starting from b->in[b->in_pos]. Caller 24800f66f451Sopenharmony_ci * must have set s->temp.pos to indicate how much data we are supposed 24810f66f451Sopenharmony_ci * to copy into s->temp.buf. Return true once s->temp.pos has reached 24820f66f451Sopenharmony_ci * s->temp.size. 24830f66f451Sopenharmony_ci */ 24840f66f451Sopenharmony_cistatic int fill_temp(struct xz_dec *s, struct xz_buf *b) 24850f66f451Sopenharmony_ci{ 24860f66f451Sopenharmony_ci size_t copy_size = minof(b->in_size - b->in_pos, s->temp.size - s->temp.pos); 24870f66f451Sopenharmony_ci 24880f66f451Sopenharmony_ci memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size); 24890f66f451Sopenharmony_ci b->in_pos += copy_size; 24900f66f451Sopenharmony_ci s->temp.pos += copy_size; 24910f66f451Sopenharmony_ci 24920f66f451Sopenharmony_ci if (s->temp.pos == s->temp.size) { 24930f66f451Sopenharmony_ci s->temp.pos = 0; 24940f66f451Sopenharmony_ci return 1; 24950f66f451Sopenharmony_ci } 24960f66f451Sopenharmony_ci 24970f66f451Sopenharmony_ci return 0; 24980f66f451Sopenharmony_ci} 24990f66f451Sopenharmony_ci 25000f66f451Sopenharmony_ci/* Decode a variable-length integer (little-endian base-128 encoding) */ 25010f66f451Sopenharmony_cistatic enum xz_ret dec_vli(struct xz_dec *s, const uint8_t *in, 25020f66f451Sopenharmony_ci size_t *in_pos, size_t in_size) 25030f66f451Sopenharmony_ci{ 25040f66f451Sopenharmony_ci uint8_t byte; 25050f66f451Sopenharmony_ci 25060f66f451Sopenharmony_ci if (s->pos == 0) 25070f66f451Sopenharmony_ci s->vli = 0; 25080f66f451Sopenharmony_ci 25090f66f451Sopenharmony_ci while (*in_pos < in_size) { 25100f66f451Sopenharmony_ci byte = in[*in_pos]; 25110f66f451Sopenharmony_ci ++*in_pos; 25120f66f451Sopenharmony_ci 25130f66f451Sopenharmony_ci s->vli |= (vli_type)(byte & 0x7F) << s->pos; 25140f66f451Sopenharmony_ci 25150f66f451Sopenharmony_ci if ((byte & 0x80) == 0) { 25160f66f451Sopenharmony_ci /* Don't allow non-minimal encodings. */ 25170f66f451Sopenharmony_ci if (byte == 0 && s->pos != 0) 25180f66f451Sopenharmony_ci return XZ_DATA_ERROR; 25190f66f451Sopenharmony_ci 25200f66f451Sopenharmony_ci s->pos = 0; 25210f66f451Sopenharmony_ci return XZ_STREAM_END; 25220f66f451Sopenharmony_ci } 25230f66f451Sopenharmony_ci 25240f66f451Sopenharmony_ci s->pos += 7; 25250f66f451Sopenharmony_ci if (s->pos == 7 * VLI_BYTES_MAX) 25260f66f451Sopenharmony_ci return XZ_DATA_ERROR; 25270f66f451Sopenharmony_ci } 25280f66f451Sopenharmony_ci 25290f66f451Sopenharmony_ci return XZ_OK; 25300f66f451Sopenharmony_ci} 25310f66f451Sopenharmony_ci 25320f66f451Sopenharmony_ci/* 25330f66f451Sopenharmony_ci * Decode the Compressed Data field from a Block. Update and validate 25340f66f451Sopenharmony_ci * the observed compressed and uncompressed sizes of the Block so that 25350f66f451Sopenharmony_ci * they don't exceed the values possibly stored in the Block Header 25360f66f451Sopenharmony_ci * (validation assumes that no integer overflow occurs, since vli_type 25370f66f451Sopenharmony_ci * is normally uint64_t). Update the CRC32 or CRC64 value if presence of 25380f66f451Sopenharmony_ci * the CRC32 or CRC64 field was indicated in Stream Header. 25390f66f451Sopenharmony_ci * 25400f66f451Sopenharmony_ci * Once the decoding is finished, validate that the observed sizes match 25410f66f451Sopenharmony_ci * the sizes possibly stored in the Block Header. Update the hash and 25420f66f451Sopenharmony_ci * Block count, which are later used to validate the Index field. 25430f66f451Sopenharmony_ci */ 25440f66f451Sopenharmony_cistatic enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) 25450f66f451Sopenharmony_ci{ 25460f66f451Sopenharmony_ci enum xz_ret ret; 25470f66f451Sopenharmony_ci 25480f66f451Sopenharmony_ci s->in_start = b->in_pos; 25490f66f451Sopenharmony_ci s->out_start = b->out_pos; 25500f66f451Sopenharmony_ci 25510f66f451Sopenharmony_ci#ifdef XZ_DEC_BCJ 25520f66f451Sopenharmony_ci if (s->bcj_active) 25530f66f451Sopenharmony_ci ret = xz_dec_bcj_run(s->bcj, s->lzma2, b); 25540f66f451Sopenharmony_ci else 25550f66f451Sopenharmony_ci#endif 25560f66f451Sopenharmony_ci ret = xz_dec_lzma2_run(s->lzma2, b); 25570f66f451Sopenharmony_ci 25580f66f451Sopenharmony_ci s->block.compressed += b->in_pos - s->in_start; 25590f66f451Sopenharmony_ci s->block.uncompressed += b->out_pos - s->out_start; 25600f66f451Sopenharmony_ci 25610f66f451Sopenharmony_ci /* 25620f66f451Sopenharmony_ci * There is no need to separately check for VLI_UNKNOWN, since 25630f66f451Sopenharmony_ci * the observed sizes are always smaller than VLI_UNKNOWN. 25640f66f451Sopenharmony_ci */ 25650f66f451Sopenharmony_ci if (s->block.compressed > s->block_header.compressed 25660f66f451Sopenharmony_ci || s->block.uncompressed 25670f66f451Sopenharmony_ci > s->block_header.uncompressed) 25680f66f451Sopenharmony_ci return XZ_DATA_ERROR; 25690f66f451Sopenharmony_ci 25700f66f451Sopenharmony_ci if (s->check_type == XZ_CHECK_CRC32) 25710f66f451Sopenharmony_ci s->crc = xz_crc32(b->out + s->out_start, 25720f66f451Sopenharmony_ci b->out_pos - s->out_start, s->crc); 25730f66f451Sopenharmony_ci else if (s->check_type == XZ_CHECK_CRC64) { 25740f66f451Sopenharmony_ci s->crc = ~(s->crc); 25750f66f451Sopenharmony_ci size_t size = b->out_pos - s->out_start; 25760f66f451Sopenharmony_ci uint8_t *buf = b->out + s->out_start; 25770f66f451Sopenharmony_ci while (size) { 25780f66f451Sopenharmony_ci s->crc = xz_crc64_table[*buf++ ^ (s->crc & 0xFF)] ^ (s->crc >> 8); 25790f66f451Sopenharmony_ci --size; 25800f66f451Sopenharmony_ci } 25810f66f451Sopenharmony_ci s->crc=~(s->crc); 25820f66f451Sopenharmony_ci } 25830f66f451Sopenharmony_ci 25840f66f451Sopenharmony_ci if (ret == XZ_STREAM_END) { 25850f66f451Sopenharmony_ci if (s->block_header.compressed != VLI_UNKNOWN 25860f66f451Sopenharmony_ci && s->block_header.compressed 25870f66f451Sopenharmony_ci != s->block.compressed) 25880f66f451Sopenharmony_ci return XZ_DATA_ERROR; 25890f66f451Sopenharmony_ci 25900f66f451Sopenharmony_ci if (s->block_header.uncompressed != VLI_UNKNOWN 25910f66f451Sopenharmony_ci && s->block_header.uncompressed 25920f66f451Sopenharmony_ci != s->block.uncompressed) 25930f66f451Sopenharmony_ci return XZ_DATA_ERROR; 25940f66f451Sopenharmony_ci 25950f66f451Sopenharmony_ci s->block.hash.unpadded += s->block_header.size 25960f66f451Sopenharmony_ci + s->block.compressed; 25970f66f451Sopenharmony_ci 25980f66f451Sopenharmony_ci s->block.hash.unpadded += check_sizes[s->check_type]; 25990f66f451Sopenharmony_ci 26000f66f451Sopenharmony_ci s->block.hash.uncompressed += s->block.uncompressed; 26010f66f451Sopenharmony_ci s->block.hash.crc32 = xz_crc32( 26020f66f451Sopenharmony_ci (const uint8_t *)&s->block.hash, 26030f66f451Sopenharmony_ci sizeof(s->block.hash), s->block.hash.crc32); 26040f66f451Sopenharmony_ci 26050f66f451Sopenharmony_ci ++s->block.count; 26060f66f451Sopenharmony_ci } 26070f66f451Sopenharmony_ci 26080f66f451Sopenharmony_ci return ret; 26090f66f451Sopenharmony_ci} 26100f66f451Sopenharmony_ci 26110f66f451Sopenharmony_ci/* Update the Index size and the CRC32 value. */ 26120f66f451Sopenharmony_cistatic void index_update(struct xz_dec *s, const struct xz_buf *b) 26130f66f451Sopenharmony_ci{ 26140f66f451Sopenharmony_ci size_t in_used = b->in_pos - s->in_start; 26150f66f451Sopenharmony_ci s->index.size += in_used; 26160f66f451Sopenharmony_ci s->crc = xz_crc32(b->in + s->in_start, in_used, s->crc); 26170f66f451Sopenharmony_ci} 26180f66f451Sopenharmony_ci 26190f66f451Sopenharmony_ci/* 26200f66f451Sopenharmony_ci * Decode the Number of Records, Unpadded Size, and Uncompressed Size 26210f66f451Sopenharmony_ci * fields from the Index field. That is, Index Padding and CRC32 are not 26220f66f451Sopenharmony_ci * decoded by this function. 26230f66f451Sopenharmony_ci * 26240f66f451Sopenharmony_ci * This can return XZ_OK (more input needed), XZ_STREAM_END (everything 26250f66f451Sopenharmony_ci * successfully decoded), or XZ_DATA_ERROR (input is corrupt). 26260f66f451Sopenharmony_ci */ 26270f66f451Sopenharmony_cistatic enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) 26280f66f451Sopenharmony_ci{ 26290f66f451Sopenharmony_ci enum xz_ret ret; 26300f66f451Sopenharmony_ci 26310f66f451Sopenharmony_ci do { 26320f66f451Sopenharmony_ci ret = dec_vli(s, b->in, &b->in_pos, b->in_size); 26330f66f451Sopenharmony_ci if (ret != XZ_STREAM_END) { 26340f66f451Sopenharmony_ci index_update(s, b); 26350f66f451Sopenharmony_ci return ret; 26360f66f451Sopenharmony_ci } 26370f66f451Sopenharmony_ci 26380f66f451Sopenharmony_ci switch (s->index.sequence) { 26390f66f451Sopenharmony_ci case SEQ_INDEX_COUNT: 26400f66f451Sopenharmony_ci s->index.count = s->vli; 26410f66f451Sopenharmony_ci 26420f66f451Sopenharmony_ci /* 26430f66f451Sopenharmony_ci * Validate that the Number of Records field 26440f66f451Sopenharmony_ci * indicates the same number of Records as 26450f66f451Sopenharmony_ci * there were Blocks in the Stream. 26460f66f451Sopenharmony_ci */ 26470f66f451Sopenharmony_ci if (s->index.count != s->block.count) 26480f66f451Sopenharmony_ci return XZ_DATA_ERROR; 26490f66f451Sopenharmony_ci 26500f66f451Sopenharmony_ci s->index.sequence = SEQ_INDEX_UNPADDED; 26510f66f451Sopenharmony_ci break; 26520f66f451Sopenharmony_ci 26530f66f451Sopenharmony_ci case SEQ_INDEX_UNPADDED: 26540f66f451Sopenharmony_ci s->index.hash.unpadded += s->vli; 26550f66f451Sopenharmony_ci s->index.sequence = SEQ_INDEX_UNCOMPRESSED; 26560f66f451Sopenharmony_ci break; 26570f66f451Sopenharmony_ci 26580f66f451Sopenharmony_ci case SEQ_INDEX_UNCOMPRESSED: 26590f66f451Sopenharmony_ci s->index.hash.uncompressed += s->vli; 26600f66f451Sopenharmony_ci s->index.hash.crc32 = xz_crc32( 26610f66f451Sopenharmony_ci (const uint8_t *)&s->index.hash, 26620f66f451Sopenharmony_ci sizeof(s->index.hash), 26630f66f451Sopenharmony_ci s->index.hash.crc32); 26640f66f451Sopenharmony_ci --s->index.count; 26650f66f451Sopenharmony_ci s->index.sequence = SEQ_INDEX_UNPADDED; 26660f66f451Sopenharmony_ci break; 26670f66f451Sopenharmony_ci } 26680f66f451Sopenharmony_ci } while (s->index.count > 0); 26690f66f451Sopenharmony_ci 26700f66f451Sopenharmony_ci return XZ_STREAM_END; 26710f66f451Sopenharmony_ci} 26720f66f451Sopenharmony_ci 26730f66f451Sopenharmony_ci/* 26740f66f451Sopenharmony_ci * Validate that the next four or eight input bytes match the value 26750f66f451Sopenharmony_ci * of s->crc. s->pos must be zero when starting to validate the first byte. 26760f66f451Sopenharmony_ci * The "bits" argument allows using the same code for both CRC32 and CRC64. 26770f66f451Sopenharmony_ci */ 26780f66f451Sopenharmony_cistatic enum xz_ret crc_validate(struct xz_dec *s, struct xz_buf *b, 26790f66f451Sopenharmony_ci uint32_t bits) 26800f66f451Sopenharmony_ci{ 26810f66f451Sopenharmony_ci do { 26820f66f451Sopenharmony_ci if (b->in_pos == b->in_size) 26830f66f451Sopenharmony_ci return XZ_OK; 26840f66f451Sopenharmony_ci 26850f66f451Sopenharmony_ci if (((s->crc >> s->pos) & 0xFF) != b->in[b->in_pos++]) 26860f66f451Sopenharmony_ci return XZ_DATA_ERROR; 26870f66f451Sopenharmony_ci 26880f66f451Sopenharmony_ci s->pos += 8; 26890f66f451Sopenharmony_ci 26900f66f451Sopenharmony_ci } while (s->pos < bits); 26910f66f451Sopenharmony_ci 26920f66f451Sopenharmony_ci s->crc = 0; 26930f66f451Sopenharmony_ci s->pos = 0; 26940f66f451Sopenharmony_ci 26950f66f451Sopenharmony_ci return XZ_STREAM_END; 26960f66f451Sopenharmony_ci} 26970f66f451Sopenharmony_ci 26980f66f451Sopenharmony_ci/* 26990f66f451Sopenharmony_ci * Skip over the Check field when the Check ID is not supported. 27000f66f451Sopenharmony_ci * Returns true once the whole Check field has been skipped over. 27010f66f451Sopenharmony_ci */ 27020f66f451Sopenharmony_cistatic int check_skip(struct xz_dec *s, struct xz_buf *b) 27030f66f451Sopenharmony_ci{ 27040f66f451Sopenharmony_ci while (s->pos < check_sizes[s->check_type]) { 27050f66f451Sopenharmony_ci if (b->in_pos == b->in_size) return 0; 27060f66f451Sopenharmony_ci 27070f66f451Sopenharmony_ci ++b->in_pos; 27080f66f451Sopenharmony_ci ++s->pos; 27090f66f451Sopenharmony_ci } 27100f66f451Sopenharmony_ci 27110f66f451Sopenharmony_ci s->pos = 0; 27120f66f451Sopenharmony_ci 27130f66f451Sopenharmony_ci return 1; 27140f66f451Sopenharmony_ci} 27150f66f451Sopenharmony_ci 27160f66f451Sopenharmony_ci/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */ 27170f66f451Sopenharmony_cistatic enum xz_ret dec_stream_header(struct xz_dec *s) 27180f66f451Sopenharmony_ci{ 27190f66f451Sopenharmony_ci if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE)) 27200f66f451Sopenharmony_ci return XZ_FORMAT_ERROR; 27210f66f451Sopenharmony_ci 27220f66f451Sopenharmony_ci if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0) 27230f66f451Sopenharmony_ci != get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2)) 27240f66f451Sopenharmony_ci return XZ_DATA_ERROR; 27250f66f451Sopenharmony_ci 27260f66f451Sopenharmony_ci if (s->temp.buf[HEADER_MAGIC_SIZE] != 0) 27270f66f451Sopenharmony_ci return XZ_OPTIONS_ERROR; 27280f66f451Sopenharmony_ci 27290f66f451Sopenharmony_ci /* 27300f66f451Sopenharmony_ci * Of integrity checks, we support none (Check ID = 0), 27310f66f451Sopenharmony_ci * CRC32 (Check ID = 1), and optionally CRC64 (Check ID = 4). 27320f66f451Sopenharmony_ci * However, if XZ_DEC_ANY_CHECK is defined, we will accept other 27330f66f451Sopenharmony_ci * check types too, but then the check won't be verified and 27340f66f451Sopenharmony_ci * a warning (XZ_UNSUPPORTED_CHECK) will be given. 27350f66f451Sopenharmony_ci */ 27360f66f451Sopenharmony_ci s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1]; 27370f66f451Sopenharmony_ci 27380f66f451Sopenharmony_ci if (s->check_type > XZ_CHECK_MAX) 27390f66f451Sopenharmony_ci return XZ_OPTIONS_ERROR; 27400f66f451Sopenharmony_ci 27410f66f451Sopenharmony_ci if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type)) 27420f66f451Sopenharmony_ci return XZ_UNSUPPORTED_CHECK; 27430f66f451Sopenharmony_ci 27440f66f451Sopenharmony_ci return XZ_OK; 27450f66f451Sopenharmony_ci} 27460f66f451Sopenharmony_ci 27470f66f451Sopenharmony_ci/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */ 27480f66f451Sopenharmony_cistatic enum xz_ret dec_stream_footer(struct xz_dec *s) 27490f66f451Sopenharmony_ci{ 27500f66f451Sopenharmony_ci if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE)) 27510f66f451Sopenharmony_ci return XZ_DATA_ERROR; 27520f66f451Sopenharmony_ci 27530f66f451Sopenharmony_ci if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf)) 27540f66f451Sopenharmony_ci return XZ_DATA_ERROR; 27550f66f451Sopenharmony_ci 27560f66f451Sopenharmony_ci /* 27570f66f451Sopenharmony_ci * Validate Backward Size. Note that we never added the size of the 27580f66f451Sopenharmony_ci * Index CRC32 field to s->index.size, thus we use s->index.size / 4 27590f66f451Sopenharmony_ci * instead of s->index.size / 4 - 1. 27600f66f451Sopenharmony_ci */ 27610f66f451Sopenharmony_ci if ((s->index.size >> 2) != get_le32(s->temp.buf + 4)) 27620f66f451Sopenharmony_ci return XZ_DATA_ERROR; 27630f66f451Sopenharmony_ci 27640f66f451Sopenharmony_ci if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type) 27650f66f451Sopenharmony_ci return XZ_DATA_ERROR; 27660f66f451Sopenharmony_ci 27670f66f451Sopenharmony_ci /* 27680f66f451Sopenharmony_ci * Use XZ_STREAM_END instead of XZ_OK to be more convenient 27690f66f451Sopenharmony_ci * for the caller. 27700f66f451Sopenharmony_ci */ 27710f66f451Sopenharmony_ci return XZ_STREAM_END; 27720f66f451Sopenharmony_ci} 27730f66f451Sopenharmony_ci 27740f66f451Sopenharmony_ci/* Decode the Block Header and initialize the filter chain. */ 27750f66f451Sopenharmony_cistatic enum xz_ret dec_block_header(struct xz_dec *s) 27760f66f451Sopenharmony_ci{ 27770f66f451Sopenharmony_ci enum xz_ret ret; 27780f66f451Sopenharmony_ci 27790f66f451Sopenharmony_ci /* 27800f66f451Sopenharmony_ci * Validate the CRC32. We know that the temp buffer is at least 27810f66f451Sopenharmony_ci * eight bytes so this is safe. 27820f66f451Sopenharmony_ci */ 27830f66f451Sopenharmony_ci s->temp.size -= 4; 27840f66f451Sopenharmony_ci if (xz_crc32(s->temp.buf, s->temp.size, 0) 27850f66f451Sopenharmony_ci != get_le32(s->temp.buf + s->temp.size)) 27860f66f451Sopenharmony_ci return XZ_DATA_ERROR; 27870f66f451Sopenharmony_ci 27880f66f451Sopenharmony_ci s->temp.pos = 2; 27890f66f451Sopenharmony_ci 27900f66f451Sopenharmony_ci /* 27910f66f451Sopenharmony_ci * Catch unsupported Block Flags. We support only one or two filters 27920f66f451Sopenharmony_ci * in the chain, so we catch that with the same test. 27930f66f451Sopenharmony_ci */ 27940f66f451Sopenharmony_ci#ifdef XZ_DEC_BCJ 27950f66f451Sopenharmony_ci if (s->temp.buf[1] & 0x3E) 27960f66f451Sopenharmony_ci#else 27970f66f451Sopenharmony_ci if (s->temp.buf[1] & 0x3F) 27980f66f451Sopenharmony_ci#endif 27990f66f451Sopenharmony_ci return XZ_OPTIONS_ERROR; 28000f66f451Sopenharmony_ci 28010f66f451Sopenharmony_ci /* Compressed Size */ 28020f66f451Sopenharmony_ci if (s->temp.buf[1] & 0x40) { 28030f66f451Sopenharmony_ci if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) 28040f66f451Sopenharmony_ci != XZ_STREAM_END) 28050f66f451Sopenharmony_ci return XZ_DATA_ERROR; 28060f66f451Sopenharmony_ci 28070f66f451Sopenharmony_ci s->block_header.compressed = s->vli; 28080f66f451Sopenharmony_ci } else { 28090f66f451Sopenharmony_ci s->block_header.compressed = VLI_UNKNOWN; 28100f66f451Sopenharmony_ci } 28110f66f451Sopenharmony_ci 28120f66f451Sopenharmony_ci /* Uncompressed Size */ 28130f66f451Sopenharmony_ci if (s->temp.buf[1] & 0x80) { 28140f66f451Sopenharmony_ci if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) 28150f66f451Sopenharmony_ci != XZ_STREAM_END) 28160f66f451Sopenharmony_ci return XZ_DATA_ERROR; 28170f66f451Sopenharmony_ci 28180f66f451Sopenharmony_ci s->block_header.uncompressed = s->vli; 28190f66f451Sopenharmony_ci } else { 28200f66f451Sopenharmony_ci s->block_header.uncompressed = VLI_UNKNOWN; 28210f66f451Sopenharmony_ci } 28220f66f451Sopenharmony_ci 28230f66f451Sopenharmony_ci#ifdef XZ_DEC_BCJ 28240f66f451Sopenharmony_ci /* If there are two filters, the first one must be a BCJ filter. */ 28250f66f451Sopenharmony_ci s->bcj_active = s->temp.buf[1] & 0x01; 28260f66f451Sopenharmony_ci if (s->bcj_active) { 28270f66f451Sopenharmony_ci if (s->temp.size - s->temp.pos < 2) 28280f66f451Sopenharmony_ci return XZ_OPTIONS_ERROR; 28290f66f451Sopenharmony_ci 28300f66f451Sopenharmony_ci ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]); 28310f66f451Sopenharmony_ci if (ret != XZ_OK) 28320f66f451Sopenharmony_ci return ret; 28330f66f451Sopenharmony_ci 28340f66f451Sopenharmony_ci /* 28350f66f451Sopenharmony_ci * We don't support custom start offset, 28360f66f451Sopenharmony_ci * so Size of Properties must be zero. 28370f66f451Sopenharmony_ci */ 28380f66f451Sopenharmony_ci if (s->temp.buf[s->temp.pos++] != 0x00) 28390f66f451Sopenharmony_ci return XZ_OPTIONS_ERROR; 28400f66f451Sopenharmony_ci } 28410f66f451Sopenharmony_ci#endif 28420f66f451Sopenharmony_ci 28430f66f451Sopenharmony_ci /* Valid Filter Flags always take at least two bytes. */ 28440f66f451Sopenharmony_ci if (s->temp.size - s->temp.pos < 2) 28450f66f451Sopenharmony_ci return XZ_DATA_ERROR; 28460f66f451Sopenharmony_ci 28470f66f451Sopenharmony_ci /* Filter ID = LZMA2 */ 28480f66f451Sopenharmony_ci if (s->temp.buf[s->temp.pos++] != 0x21) 28490f66f451Sopenharmony_ci return XZ_OPTIONS_ERROR; 28500f66f451Sopenharmony_ci 28510f66f451Sopenharmony_ci /* Size of Properties = 1-byte Filter Properties */ 28520f66f451Sopenharmony_ci if (s->temp.buf[s->temp.pos++] != 0x01) 28530f66f451Sopenharmony_ci return XZ_OPTIONS_ERROR; 28540f66f451Sopenharmony_ci 28550f66f451Sopenharmony_ci /* Filter Properties contains LZMA2 dictionary size. */ 28560f66f451Sopenharmony_ci if (s->temp.size - s->temp.pos < 1) 28570f66f451Sopenharmony_ci return XZ_DATA_ERROR; 28580f66f451Sopenharmony_ci 28590f66f451Sopenharmony_ci ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]); 28600f66f451Sopenharmony_ci if (ret != XZ_OK) 28610f66f451Sopenharmony_ci return ret; 28620f66f451Sopenharmony_ci 28630f66f451Sopenharmony_ci /* The rest must be Header Padding. */ 28640f66f451Sopenharmony_ci while (s->temp.pos < s->temp.size) 28650f66f451Sopenharmony_ci if (s->temp.buf[s->temp.pos++] != 0x00) 28660f66f451Sopenharmony_ci return XZ_OPTIONS_ERROR; 28670f66f451Sopenharmony_ci 28680f66f451Sopenharmony_ci s->temp.pos = 0; 28690f66f451Sopenharmony_ci s->block.compressed = 0; 28700f66f451Sopenharmony_ci s->block.uncompressed = 0; 28710f66f451Sopenharmony_ci 28720f66f451Sopenharmony_ci return XZ_OK; 28730f66f451Sopenharmony_ci} 28740f66f451Sopenharmony_ci 28750f66f451Sopenharmony_cistatic enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) 28760f66f451Sopenharmony_ci{ 28770f66f451Sopenharmony_ci enum xz_ret ret; 28780f66f451Sopenharmony_ci 28790f66f451Sopenharmony_ci /* 28800f66f451Sopenharmony_ci * Store the start position for the case when we are in the middle 28810f66f451Sopenharmony_ci * of the Index field. 28820f66f451Sopenharmony_ci */ 28830f66f451Sopenharmony_ci s->in_start = b->in_pos; 28840f66f451Sopenharmony_ci 28850f66f451Sopenharmony_ci for (;;) { 28860f66f451Sopenharmony_ci switch (s->sequence) { 28870f66f451Sopenharmony_ci case SEQ_STREAM_HEADER: 28880f66f451Sopenharmony_ci /* 28890f66f451Sopenharmony_ci * Stream Header is copied to s->temp, and then 28900f66f451Sopenharmony_ci * decoded from there. This way if the caller 28910f66f451Sopenharmony_ci * gives us only little input at a time, we can 28920f66f451Sopenharmony_ci * still keep the Stream Header decoding code 28930f66f451Sopenharmony_ci * simple. Similar approach is used in many places 28940f66f451Sopenharmony_ci * in this file. 28950f66f451Sopenharmony_ci */ 28960f66f451Sopenharmony_ci if (!fill_temp(s, b)) 28970f66f451Sopenharmony_ci return XZ_OK; 28980f66f451Sopenharmony_ci 28990f66f451Sopenharmony_ci /* 29000f66f451Sopenharmony_ci * If dec_stream_header() returns 29010f66f451Sopenharmony_ci * XZ_UNSUPPORTED_CHECK, it is still possible 29020f66f451Sopenharmony_ci * to continue decoding if working in multi-call 29030f66f451Sopenharmony_ci * mode. Thus, update s->sequence before calling 29040f66f451Sopenharmony_ci * dec_stream_header(). 29050f66f451Sopenharmony_ci */ 29060f66f451Sopenharmony_ci s->sequence = SEQ_BLOCK_START; 29070f66f451Sopenharmony_ci 29080f66f451Sopenharmony_ci ret = dec_stream_header(s); 29090f66f451Sopenharmony_ci if (ret != XZ_OK) 29100f66f451Sopenharmony_ci return ret; 29110f66f451Sopenharmony_ci 29120f66f451Sopenharmony_ci case SEQ_BLOCK_START: 29130f66f451Sopenharmony_ci /* We need one byte of input to continue. */ 29140f66f451Sopenharmony_ci if (b->in_pos == b->in_size) 29150f66f451Sopenharmony_ci return XZ_OK; 29160f66f451Sopenharmony_ci 29170f66f451Sopenharmony_ci /* See if this is the beginning of the Index field. */ 29180f66f451Sopenharmony_ci if (b->in[b->in_pos] == 0) { 29190f66f451Sopenharmony_ci s->in_start = b->in_pos++; 29200f66f451Sopenharmony_ci s->sequence = SEQ_INDEX; 29210f66f451Sopenharmony_ci break; 29220f66f451Sopenharmony_ci } 29230f66f451Sopenharmony_ci 29240f66f451Sopenharmony_ci /* 29250f66f451Sopenharmony_ci * Calculate the size of the Block Header and 29260f66f451Sopenharmony_ci * prepare to decode it. 29270f66f451Sopenharmony_ci */ 29280f66f451Sopenharmony_ci s->block_header.size 29290f66f451Sopenharmony_ci = ((uint32_t)b->in[b->in_pos] + 1) * 4; 29300f66f451Sopenharmony_ci 29310f66f451Sopenharmony_ci s->temp.size = s->block_header.size; 29320f66f451Sopenharmony_ci s->temp.pos = 0; 29330f66f451Sopenharmony_ci s->sequence = SEQ_BLOCK_HEADER; 29340f66f451Sopenharmony_ci 29350f66f451Sopenharmony_ci case SEQ_BLOCK_HEADER: 29360f66f451Sopenharmony_ci if (!fill_temp(s, b)) 29370f66f451Sopenharmony_ci return XZ_OK; 29380f66f451Sopenharmony_ci 29390f66f451Sopenharmony_ci ret = dec_block_header(s); 29400f66f451Sopenharmony_ci if (ret != XZ_OK) 29410f66f451Sopenharmony_ci return ret; 29420f66f451Sopenharmony_ci 29430f66f451Sopenharmony_ci s->sequence = SEQ_BLOCK_UNCOMPRESS; 29440f66f451Sopenharmony_ci 29450f66f451Sopenharmony_ci case SEQ_BLOCK_UNCOMPRESS: 29460f66f451Sopenharmony_ci ret = dec_block(s, b); 29470f66f451Sopenharmony_ci if (ret != XZ_STREAM_END) 29480f66f451Sopenharmony_ci return ret; 29490f66f451Sopenharmony_ci 29500f66f451Sopenharmony_ci s->sequence = SEQ_BLOCK_PADDING; 29510f66f451Sopenharmony_ci 29520f66f451Sopenharmony_ci case SEQ_BLOCK_PADDING: 29530f66f451Sopenharmony_ci /* 29540f66f451Sopenharmony_ci * Size of Compressed Data + Block Padding 29550f66f451Sopenharmony_ci * must be a multiple of four. We don't need 29560f66f451Sopenharmony_ci * s->block.compressed for anything else 29570f66f451Sopenharmony_ci * anymore, so we use it here to test the size 29580f66f451Sopenharmony_ci * of the Block Padding field. 29590f66f451Sopenharmony_ci */ 29600f66f451Sopenharmony_ci while (s->block.compressed & 3) { 29610f66f451Sopenharmony_ci if (b->in_pos == b->in_size) 29620f66f451Sopenharmony_ci return XZ_OK; 29630f66f451Sopenharmony_ci 29640f66f451Sopenharmony_ci if (b->in[b->in_pos++] != 0) 29650f66f451Sopenharmony_ci return XZ_DATA_ERROR; 29660f66f451Sopenharmony_ci 29670f66f451Sopenharmony_ci ++s->block.compressed; 29680f66f451Sopenharmony_ci } 29690f66f451Sopenharmony_ci 29700f66f451Sopenharmony_ci s->sequence = SEQ_BLOCK_CHECK; 29710f66f451Sopenharmony_ci 29720f66f451Sopenharmony_ci case SEQ_BLOCK_CHECK: 29730f66f451Sopenharmony_ci if (s->check_type == XZ_CHECK_CRC32) { 29740f66f451Sopenharmony_ci ret = crc_validate(s, b, 32); 29750f66f451Sopenharmony_ci if (ret != XZ_STREAM_END) 29760f66f451Sopenharmony_ci return ret; 29770f66f451Sopenharmony_ci } 29780f66f451Sopenharmony_ci else if (IS_CRC64(s->check_type)) { 29790f66f451Sopenharmony_ci ret = crc_validate(s, b, 64); 29800f66f451Sopenharmony_ci if (ret != XZ_STREAM_END) 29810f66f451Sopenharmony_ci return ret; 29820f66f451Sopenharmony_ci } 29830f66f451Sopenharmony_ci else if (!check_skip(s, b)) { 29840f66f451Sopenharmony_ci return XZ_OK; 29850f66f451Sopenharmony_ci } 29860f66f451Sopenharmony_ci 29870f66f451Sopenharmony_ci s->sequence = SEQ_BLOCK_START; 29880f66f451Sopenharmony_ci break; 29890f66f451Sopenharmony_ci 29900f66f451Sopenharmony_ci case SEQ_INDEX: 29910f66f451Sopenharmony_ci ret = dec_index(s, b); 29920f66f451Sopenharmony_ci if (ret != XZ_STREAM_END) 29930f66f451Sopenharmony_ci return ret; 29940f66f451Sopenharmony_ci 29950f66f451Sopenharmony_ci s->sequence = SEQ_INDEX_PADDING; 29960f66f451Sopenharmony_ci 29970f66f451Sopenharmony_ci case SEQ_INDEX_PADDING: 29980f66f451Sopenharmony_ci while ((s->index.size + (b->in_pos - s->in_start)) 29990f66f451Sopenharmony_ci & 3) { 30000f66f451Sopenharmony_ci if (b->in_pos == b->in_size) { 30010f66f451Sopenharmony_ci index_update(s, b); 30020f66f451Sopenharmony_ci return XZ_OK; 30030f66f451Sopenharmony_ci } 30040f66f451Sopenharmony_ci 30050f66f451Sopenharmony_ci if (b->in[b->in_pos++] != 0) 30060f66f451Sopenharmony_ci return XZ_DATA_ERROR; 30070f66f451Sopenharmony_ci } 30080f66f451Sopenharmony_ci 30090f66f451Sopenharmony_ci /* Finish the CRC32 value and Index size. */ 30100f66f451Sopenharmony_ci index_update(s, b); 30110f66f451Sopenharmony_ci 30120f66f451Sopenharmony_ci /* Compare the hashes to validate the Index field. */ 30130f66f451Sopenharmony_ci if (!memeq(&s->block.hash, &s->index.hash, 30140f66f451Sopenharmony_ci sizeof(s->block.hash))) 30150f66f451Sopenharmony_ci return XZ_DATA_ERROR; 30160f66f451Sopenharmony_ci 30170f66f451Sopenharmony_ci s->sequence = SEQ_INDEX_CRC32; 30180f66f451Sopenharmony_ci 30190f66f451Sopenharmony_ci case SEQ_INDEX_CRC32: 30200f66f451Sopenharmony_ci ret = crc_validate(s, b, 32); 30210f66f451Sopenharmony_ci if (ret != XZ_STREAM_END) 30220f66f451Sopenharmony_ci return ret; 30230f66f451Sopenharmony_ci 30240f66f451Sopenharmony_ci s->temp.size = STREAM_HEADER_SIZE; 30250f66f451Sopenharmony_ci s->sequence = SEQ_STREAM_FOOTER; 30260f66f451Sopenharmony_ci 30270f66f451Sopenharmony_ci case SEQ_STREAM_FOOTER: 30280f66f451Sopenharmony_ci if (!fill_temp(s, b)) 30290f66f451Sopenharmony_ci return XZ_OK; 30300f66f451Sopenharmony_ci 30310f66f451Sopenharmony_ci return dec_stream_footer(s); 30320f66f451Sopenharmony_ci } 30330f66f451Sopenharmony_ci } 30340f66f451Sopenharmony_ci 30350f66f451Sopenharmony_ci /* Never reached */ 30360f66f451Sopenharmony_ci} 30370f66f451Sopenharmony_ci 30380f66f451Sopenharmony_ci/* 30390f66f451Sopenharmony_ci * xz_dec_run() is a wrapper for dec_main() to handle some special cases in 30400f66f451Sopenharmony_ci * multi-call and single-call decoding. 30410f66f451Sopenharmony_ci * 30420f66f451Sopenharmony_ci * In multi-call mode, we must return XZ_BUF_ERROR when it seems clear that we 30430f66f451Sopenharmony_ci * are not going to make any progress anymore. This is to prevent the caller 30440f66f451Sopenharmony_ci * from calling us infinitely when the input file is truncated or otherwise 30450f66f451Sopenharmony_ci * corrupt. Since zlib-style API allows that the caller fills the input buffer 30460f66f451Sopenharmony_ci * only when the decoder doesn't produce any new output, we have to be careful 30470f66f451Sopenharmony_ci * to avoid returning XZ_BUF_ERROR too easily: XZ_BUF_ERROR is returned only 30480f66f451Sopenharmony_ci * after the second consecutive call to xz_dec_run() that makes no progress. 30490f66f451Sopenharmony_ci * 30500f66f451Sopenharmony_ci * In single-call mode, if we couldn't decode everything and no error 30510f66f451Sopenharmony_ci * occurred, either the input is truncated or the output buffer is too small. 30520f66f451Sopenharmony_ci * Since we know that the last input byte never produces any output, we know 30530f66f451Sopenharmony_ci * that if all the input was consumed and decoding wasn't finished, the file 30540f66f451Sopenharmony_ci * must be corrupt. Otherwise the output buffer has to be too small or the 30550f66f451Sopenharmony_ci * file is corrupt in a way that decoding it produces too big output. 30560f66f451Sopenharmony_ci * 30570f66f451Sopenharmony_ci * If single-call decoding fails, we reset b->in_pos and b->out_pos back to 30580f66f451Sopenharmony_ci * their original values. This is because with some filter chains there won't 30590f66f451Sopenharmony_ci * be any valid uncompressed data in the output buffer unless the decoding 30600f66f451Sopenharmony_ci * actually succeeds (that's the price to pay of using the output buffer as 30610f66f451Sopenharmony_ci * the workspace). 30620f66f451Sopenharmony_ci */ 30630f66f451Sopenharmony_cienum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b) 30640f66f451Sopenharmony_ci{ 30650f66f451Sopenharmony_ci size_t in_start; 30660f66f451Sopenharmony_ci size_t out_start; 30670f66f451Sopenharmony_ci enum xz_ret ret; 30680f66f451Sopenharmony_ci 30690f66f451Sopenharmony_ci in_start = b->in_pos; 30700f66f451Sopenharmony_ci out_start = b->out_pos; 30710f66f451Sopenharmony_ci ret = dec_main(s, b); 30720f66f451Sopenharmony_ci 30730f66f451Sopenharmony_ci if (ret == XZ_OK && in_start == b->in_pos && out_start == b->out_pos) { 30740f66f451Sopenharmony_ci if (s->allow_buf_error) 30750f66f451Sopenharmony_ci ret = XZ_BUF_ERROR; 30760f66f451Sopenharmony_ci 30770f66f451Sopenharmony_ci s->allow_buf_error = 1; 30780f66f451Sopenharmony_ci } else { 30790f66f451Sopenharmony_ci s->allow_buf_error = 0; 30800f66f451Sopenharmony_ci } 30810f66f451Sopenharmony_ci 30820f66f451Sopenharmony_ci return ret; 30830f66f451Sopenharmony_ci} 30840f66f451Sopenharmony_ci 30850f66f451Sopenharmony_cistruct xz_dec *xz_dec_init(uint32_t dict_max) 30860f66f451Sopenharmony_ci{ 30870f66f451Sopenharmony_ci struct xz_dec *s = malloc(sizeof(*s)); 30880f66f451Sopenharmony_ci if (!s) 30890f66f451Sopenharmony_ci return NULL; 30900f66f451Sopenharmony_ci 30910f66f451Sopenharmony_ci#ifdef XZ_DEC_BCJ 30920f66f451Sopenharmony_ci s->bcj = malloc(sizeof(*s->bcj)); 30930f66f451Sopenharmony_ci if (!s->bcj) 30940f66f451Sopenharmony_ci goto error_bcj; 30950f66f451Sopenharmony_ci#endif 30960f66f451Sopenharmony_ci 30970f66f451Sopenharmony_ci s->lzma2 = xz_dec_lzma2_create(dict_max); 30980f66f451Sopenharmony_ci if (s->lzma2 == NULL) 30990f66f451Sopenharmony_ci goto error_lzma2; 31000f66f451Sopenharmony_ci 31010f66f451Sopenharmony_ci xz_dec_reset(s); 31020f66f451Sopenharmony_ci return s; 31030f66f451Sopenharmony_ci 31040f66f451Sopenharmony_cierror_lzma2: 31050f66f451Sopenharmony_ci#ifdef XZ_DEC_BCJ 31060f66f451Sopenharmony_ci free(s->bcj); 31070f66f451Sopenharmony_cierror_bcj: 31080f66f451Sopenharmony_ci#endif 31090f66f451Sopenharmony_ci free(s); 31100f66f451Sopenharmony_ci return NULL; 31110f66f451Sopenharmony_ci} 31120f66f451Sopenharmony_ci 31130f66f451Sopenharmony_civoid xz_dec_reset(struct xz_dec *s) 31140f66f451Sopenharmony_ci{ 31150f66f451Sopenharmony_ci s->sequence = SEQ_STREAM_HEADER; 31160f66f451Sopenharmony_ci s->allow_buf_error = 0; 31170f66f451Sopenharmony_ci s->pos = 0; 31180f66f451Sopenharmony_ci s->crc = 0; 31190f66f451Sopenharmony_ci memset(&s->block, 0, sizeof(s->block)); 31200f66f451Sopenharmony_ci memset(&s->index, 0, sizeof(s->index)); 31210f66f451Sopenharmony_ci s->temp.pos = 0; 31220f66f451Sopenharmony_ci s->temp.size = STREAM_HEADER_SIZE; 31230f66f451Sopenharmony_ci} 31240f66f451Sopenharmony_ci 31250f66f451Sopenharmony_civoid xz_dec_end(struct xz_dec *s) 31260f66f451Sopenharmony_ci{ 31270f66f451Sopenharmony_ci if (s != NULL) { 31280f66f451Sopenharmony_ci free((s->lzma2)->dict.buf); 31290f66f451Sopenharmony_ci free(s->lzma2); 31300f66f451Sopenharmony_ci 31310f66f451Sopenharmony_ci#ifdef XZ_DEC_BCJ 31320f66f451Sopenharmony_ci free(s->bcj); 31330f66f451Sopenharmony_ci#endif 31340f66f451Sopenharmony_ci free(s); 31350f66f451Sopenharmony_ci } 31360f66f451Sopenharmony_ci} 3137