Rizin
unix-like reverse engineering framework and cli tools
zip_algorithm_xz.c File Reference
#include "zipint.h"
#include <limits.h>
#include <lzma.h>
#include <stdlib.h>
#include <zlib.h>

Go to the source code of this file.

Classes

struct  ctx
 

Macros

#define HEADER_BYTES_ZIP   9
 
#define HEADER_MAGIC_LENGTH   4
 
#define HEADER_MAGIC1_OFFSET   0
 
#define HEADER_MAGIC2_OFFSET   2
 
#define HEADER_SIZE_OFFSET   9
 
#define HEADER_SIZE_LENGTH   8
 
#define HEADER_PARAMETERS_LENGTH   5
 
#define HEADER_LZMA_ALONE_LENGTH   (HEADER_PARAMETERS_LENGTH + HEADER_SIZE_LENGTH)
 

Enumerations

enum  header_state { INCOMPLETE , OUTPUT , DONE }
 

Functions

static zip_uint64_t maximum_compressed_size (zip_uint64_t uncompressed_size)
 
static void * allocate (bool compress, int compression_flags, zip_error_t *error, zip_uint16_t method)
 
static void * compress_allocate (zip_uint16_t method, int compression_flags, zip_error_t *error)
 
static void * decompress_allocate (zip_uint16_t method, int compression_flags, zip_error_t *error)
 
static void deallocate (void *ud)
 
static zip_uint16_t general_purpose_bit_flags (void *ud)
 
static int map_error (lzma_ret ret)
 
static bool start (void *ud, zip_stat_t *st, zip_file_attributes_t *attributes)
 
static bool end (void *ud)
 
static bool input (void *ud, zip_uint8_t *data, zip_uint64_t length)
 
static void end_of_input (void *ud)
 
static zip_compression_status_t process (void *ud, zip_uint8_t *data, zip_uint64_t *length)
 

Variables

zip_compression_algorithm_t zip_algorithm_xz_compress
 
zip_compression_algorithm_t zip_algorithm_xz_decompress
 

Macro Definition Documentation

◆ HEADER_BYTES_ZIP

#define HEADER_BYTES_ZIP   9

Definition at line 44 of file zip_algorithm_xz.c.

◆ HEADER_LZMA_ALONE_LENGTH

#define HEADER_LZMA_ALONE_LENGTH   (HEADER_PARAMETERS_LENGTH + HEADER_SIZE_LENGTH)

Definition at line 51 of file zip_algorithm_xz.c.

◆ HEADER_MAGIC1_OFFSET

#define HEADER_MAGIC1_OFFSET   0

Definition at line 46 of file zip_algorithm_xz.c.

◆ HEADER_MAGIC2_OFFSET

#define HEADER_MAGIC2_OFFSET   2

Definition at line 47 of file zip_algorithm_xz.c.

◆ HEADER_MAGIC_LENGTH

#define HEADER_MAGIC_LENGTH   4

Definition at line 45 of file zip_algorithm_xz.c.

◆ HEADER_PARAMETERS_LENGTH

#define HEADER_PARAMETERS_LENGTH   5

Definition at line 50 of file zip_algorithm_xz.c.

◆ HEADER_SIZE_LENGTH

#define HEADER_SIZE_LENGTH   8

Definition at line 49 of file zip_algorithm_xz.c.

◆ HEADER_SIZE_OFFSET

#define HEADER_SIZE_OFFSET   9

Definition at line 48 of file zip_algorithm_xz.c.

Enumeration Type Documentation

◆ header_state

Enumerator
INCOMPLETE 
OUTPUT 
DONE 

Definition at line 42 of file zip_algorithm_xz.c.

42 { INCOMPLETE, OUTPUT, DONE };
@ INCOMPLETE
@ OUTPUT
@ DONE

Function Documentation

◆ allocate()

static void* allocate ( bool  compress,
int  compression_flags,
zip_error_t error,
zip_uint16_t  method 
)
static

Definition at line 107 of file zip_algorithm_xz.c.

107  {
108  struct ctx *ctx;
109 
110  if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
112  return NULL;
113  }
114 
115  ctx->error = error;
116  ctx->compress = compress;
117  if (compression_flags < 0 || compression_flags > 9) {
118  ctx->compression_flags = 6; /* default value */
119  } else {
121  }
123  ctx->end_of_input = false;
124  memset(ctx->header, 0, sizeof(ctx->header));
126  if (ZIP_CM_LZMA) {
128  }
129  else {
130  ctx->header_state = DONE;
131  }
132  memset(&ctx->zstr, 0, sizeof(ctx->zstr));
133  ctx->method = method;
134  return ctx;
135 }
int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
Definition: compress.c:68
#define LZMA_PRESET_EXTREME
Extreme compression preset.
Definition: container.h:60
#define NULL
Definition: cris-opc.c:27
return memset(p, 0, total)
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int)
Definition: zip_error.c:126
#define ZIP_ER_MEMORY
Definition: zip.h:119
#define ZIP_CM_LZMA
Definition: zip.h:163
void * malloc(size_t size)
Definition: malloc.c:123
zip_uint8_t header_bytes_offset
zip_uint16_t method
bool end_of_input
zip_uint8_t header[HEADER_MAGIC_LENGTH+HEADER_LZMA_ALONE_LENGTH]
bz_stream zstr
int compression_flags
enum header_state header_state
bool compress
zip_error_t * error
void error(const char *msg)
Definition: untgz.c:593
uint32_t zip_uint32_t
Definition: zipconf.h:37

References ctx::compress, compress(), ctx::compression_flags, DONE, ctx::end_of_input, ctx::error, error(), ctx::header, ctx::header_bytes_offset, ctx::header_state, INCOMPLETE, LZMA_PRESET_EXTREME, malloc(), memset(), ctx::method, NULL, ZIP_CM_LZMA, ZIP_ER_MEMORY, zip_error_set(), and ctx::zstr.

Referenced by compress_allocate(), and decompress_allocate().

◆ compress_allocate()

static void* compress_allocate ( zip_uint16_t  method,
int  compression_flags,
zip_error_t error 
)
static

Definition at line 139 of file zip_algorithm_xz.c.

139  {
140  return allocate(true, compression_flags, error, method);
141 }
static void * allocate(bool compress, int compression_flags, zip_error_t *error, zip_uint16_t method)

References allocate(), ctx::compression_flags, error(), and ctx::method.

◆ deallocate()

static void deallocate ( void *  ud)
static

Definition at line 151 of file zip_algorithm_xz.c.

151  {
152  struct ctx *ctx = (struct ctx *)ud;
153  free(ctx);
154 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130

References free().

◆ decompress_allocate()

static void* decompress_allocate ( zip_uint16_t  method,
int  compression_flags,
zip_error_t error 
)
static

Definition at line 145 of file zip_algorithm_xz.c.

145  {
146  return allocate(false, compression_flags, error, method);
147 }

References allocate(), ctx::compression_flags, error(), and ctx::method.

◆ end()

static bool end ( void *  ud)
static

Definition at line 240 of file zip_algorithm_xz.c.

240  {
241  struct ctx *ctx = (struct ctx *)ud;
242 
243  lzma_end(&ctx->zstr);
244  return true;
245 }

References ctx::zstr.

◆ end_of_input()

static void end_of_input ( void *  ud)
static

Definition at line 306 of file zip_algorithm_xz.c.

306  {
307  struct ctx *ctx = (struct ctx *)ud;
308 
309  ctx->end_of_input = true;
310 }

References ctx::end_of_input.

◆ general_purpose_bit_flags()

static zip_uint16_t general_purpose_bit_flags ( void *  ud)
static

Definition at line 158 of file zip_algorithm_xz.c.

158  {
159  struct ctx *ctx = (struct ctx *)ud;
160 
161  if (!ctx->compress) {
162  return 0;
163  }
164 
165  if (ctx->method == ZIP_CM_LZMA) {
166  /* liblzma always returns an EOS/EOPM marker, see
167  * https://sourceforge.net/p/lzmautils/discussion/708858/thread/84c5dbb9/#a5e4/3764 */
168  return 1 << 1;
169  }
170  return 0;
171 }

References ctx::compress, ctx::method, and ZIP_CM_LZMA.

◆ input()

static bool input ( void *  ud,
zip_uint8_t data,
zip_uint64_t  length 
)
static

Definition at line 249 of file zip_algorithm_xz.c.

249  {
250  struct ctx *ctx = (struct ctx *)ud;
251 
252  if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
254  return false;
255  }
256 
257  /* For decompression of LZMA1: Have we read the full "lzma alone" header yet? */
259  /* if not, get more of the data */
261  memcpy(ctx->header + ctx->header_bytes_offset, data, got);
262  ctx->header_bytes_offset += got;
263  length -= got;
264  data += got;
265  /* Do we have a complete header now? */
267  Bytef empty_buffer[1];
269  /* check magic */
270  if (ctx->header[HEADER_MAGIC2_OFFSET] != 0x05 || ctx->header[HEADER_MAGIC2_OFFSET + 1] != 0x00) {
271  /* magic does not match */
273  return false;
274  }
275  /* set size of uncompressed data in "lzma alone" header to "unknown" */
278  return false;
279  }
282  /* Feed header into "lzma alone" decoder, for
283  * initialization; this should not produce output. */
284  ctx->zstr.next_in = (void *)(ctx->header + HEADER_MAGIC_LENGTH);
285  ctx->zstr.avail_in = HEADER_LZMA_ALONE_LENGTH;
286  ctx->zstr.total_in = 0;
287  ctx->zstr.next_out = empty_buffer;
288  ctx->zstr.avail_out = sizeof(*empty_buffer);
289  ctx->zstr.total_out = 0;
290  /* this just initializes the decoder and does not produce output, so it consumes the complete header */
291  if (lzma_code(&ctx->zstr, LZMA_RUN) != LZMA_OK || ctx->zstr.total_out > 0) {
293  return false;
294  }
295  ctx->header_state = DONE;
296  }
297  }
298  ctx->zstr.avail_in = (uInt)length;
299  ctx->zstr.next_in = (Bytef *)data;
300 
301  return true;
302 }
struct buffer buffer
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define ZIP_ER_COMPRESSED_DATA
Definition: zip.h:136
#define ZIP_ER_INVAL
Definition: zip.h:123
Definition: buffer.h:15
zip_uint64_t uncompresssed_size
#define UINT_MAX
Definition: md5.h:55
@ LZMA_OK
Operation completed successfully.
Definition: base.h:58
@ LZMA_RUN
Continue coding.
Definition: base.h:251
unsigned int uInt
Definition: zconf.h:393
Byte FAR Bytef
Definition: zconf.h:400
#define HEADER_MAGIC2_OFFSET
#define HEADER_SIZE_OFFSET
#define HEADER_LZMA_ALONE_LENGTH
#define HEADER_MAGIC_LENGTH
#define HEADER_BYTES_ZIP
#define HEADER_SIZE_LENGTH
zip_buffer_t * _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size)
Definition: zip_buffer.c:146
void _zip_buffer_free(zip_buffer_t *buffer)
Definition: zip_buffer.c:46
int _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i)
Definition: zip_buffer.c:262
uint8_t zip_uint8_t
Definition: zipconf.h:33
#define ZIP_MIN(a, b)
Definition: zipint.h:473

References _zip_buffer_free(), _zip_buffer_new(), _zip_buffer_put_64(), ctx::compress, DONE, ctx::error, ctx::header, ctx::header_bytes_offset, HEADER_BYTES_ZIP, HEADER_LZMA_ALONE_LENGTH, HEADER_MAGIC2_OFFSET, HEADER_MAGIC_LENGTH, HEADER_SIZE_LENGTH, HEADER_SIZE_OFFSET, ctx::header_state, INCOMPLETE, length, LZMA_OK, LZMA_RUN, memcpy(), ctx::method, NULL, UINT_MAX, ctx::uncompresssed_size, ZIP_CM_LZMA, ZIP_ER_COMPRESSED_DATA, ZIP_ER_INVAL, ZIP_ER_MEMORY, zip_error_set(), ZIP_MIN, and ctx::zstr.

◆ map_error()

static int map_error ( lzma_ret  ret)
static

Definition at line 174 of file zip_algorithm_xz.c.

174  {
175  switch (ret) {
176  case LZMA_DATA_ERROR:
178  return ZIP_ER_COMPRESSED_DATA;
179 
180  case LZMA_MEM_ERROR:
181  return ZIP_ER_MEMORY;
182 
183  case LZMA_OPTIONS_ERROR:
184  return ZIP_ER_INVAL;
185 
186  default:
187  return ZIP_ER_INTERNAL;
188  }
189 }
#define ZIP_ER_INTERNAL
Definition: zip.h:125
@ LZMA_DATA_ERROR
Data is corrupt.
Definition: base.h:172
@ LZMA_MEM_ERROR
Cannot allocate memory.
Definition: base.h:128
@ LZMA_UNSUPPORTED_CHECK
Cannot calculate the integrity check.
Definition: base.h:90
@ LZMA_OPTIONS_ERROR
Invalid or unsupported options.
Definition: base.h:160

References LZMA_DATA_ERROR, LZMA_MEM_ERROR, LZMA_OPTIONS_ERROR, LZMA_UNSUPPORTED_CHECK, ZIP_ER_COMPRESSED_DATA, ZIP_ER_INTERNAL, ZIP_ER_INVAL, and ZIP_ER_MEMORY.

Referenced by process(), and start().

◆ maximum_compressed_size()

static zip_uint64_t maximum_compressed_size ( zip_uint64_t  uncompressed_size)
static

Definition at line 86 of file zip_algorithm_xz.c.

86  {
87  /*
88  According to https://sourceforge.net/p/sevenzip/discussion/45797/thread/b6bd62f8/
89 
90  1) you can use
91  outSize = 1.10 * originalSize + 64 KB.
92  in most cases outSize is less then 1.02 from originalSize.
93  2) You can try LZMA2, where
94  outSize can be = 1.001 * originalSize + 1 KB.
95  */
96  /* 13 bytes added for lzma alone header */
97  zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.1) + 64 * 1024 + 13;
98 
100  return ZIP_UINT64_MAX;
101  }
102  return compressed_size;
103 }
uint64_t compressed_size
Definition: list.c:105
uint64_t uncompressed_size
Definition: list.c:106
uint64_t zip_uint64_t
Definition: zipconf.h:39
#define ZIP_UINT64_MAX
Definition: zipconf.h:55

References compressed_size, uncompressed_size, and ZIP_UINT64_MAX.

◆ process()

static zip_compression_status_t process ( void *  ud,
zip_uint8_t data,
zip_uint64_t length 
)
static

Definition at line 314 of file zip_algorithm_xz.c.

314  {
315  struct ctx *ctx = (struct ctx *)ud;
316  lzma_ret ret;
317  /* for compression of LZMA1 */
318  if (ctx->method == ZIP_CM_LZMA && ctx->compress) {
319  if (ctx->header_state == INCOMPLETE) {
320  /* write magic to output buffer */
321  ctx->header[0] = 0x09;
322  ctx->header[1] = 0x14;
323  ctx->header[2] = 0x05;
324  ctx->header[3] = 0x00;
325  /* generate lzma parameters into output buffer */
326  ctx->zstr.avail_out = HEADER_LZMA_ALONE_LENGTH;
327  ctx->zstr.next_out = ctx->header + HEADER_MAGIC_LENGTH;
328  ret = lzma_code(&ctx->zstr, LZMA_RUN);
329  if (ret != LZMA_OK || ctx->zstr.avail_out != 0) {
330  /* assume that the whole header will be provided with the first call to lzma_code */
331  return ZIP_COMPRESSION_ERROR;
332  }
334  }
335  if (ctx->header_state == OUTPUT) {
336  /* write header */
338  memcpy(data, ctx->header + ctx->header_bytes_offset, write_len);
339  ctx->header_bytes_offset += write_len;
340  *length = write_len;
342  ctx->header_state = DONE;
343  }
344  return ZIP_COMPRESSION_OK;
345  }
346  }
347 
348  ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
349  ctx->zstr.next_out = (Bytef *)data;
350 
351  ret = lzma_code(&ctx->zstr, ctx->end_of_input ? LZMA_FINISH : LZMA_RUN);
352  *length = *length - ctx->zstr.avail_out;
353 
354  switch (ret) {
355  case LZMA_OK:
356  return ZIP_COMPRESSION_OK;
357 
358  case LZMA_STREAM_END:
359  return ZIP_COMPRESSION_END;
360 
361  case LZMA_BUF_ERROR:
362  if (ctx->zstr.avail_in == 0) {
364  }
365 
366  /* fallthrough */
367  default:
368  zip_error_set(ctx->error, map_error(ret), 0);
369  return ZIP_COMPRESSION_ERROR;
370  }
371 }
lzma_ret
Return values used by several functions in liblzma.
Definition: base.h:57
@ LZMA_STREAM_END
End of stream was reached.
Definition: base.h:63
@ LZMA_BUF_ERROR
No progress is possible.
Definition: base.h:191
@ LZMA_FINISH
Finish the coding operation.
Definition: base.h:328
static int map_error(lzma_ret ret)
@ ZIP_COMPRESSION_NEED_DATA
Definition: zipint.h:119
@ ZIP_COMPRESSION_ERROR
Definition: zipint.h:118
@ ZIP_COMPRESSION_END
Definition: zipint.h:117
@ ZIP_COMPRESSION_OK
Definition: zipint.h:116

References ctx::compress, DONE, ctx::end_of_input, ctx::error, ctx::header, ctx::header_bytes_offset, HEADER_BYTES_ZIP, HEADER_LZMA_ALONE_LENGTH, HEADER_MAGIC_LENGTH, ctx::header_state, INCOMPLETE, length, LZMA_BUF_ERROR, LZMA_FINISH, LZMA_OK, LZMA_RUN, LZMA_STREAM_END, map_error(), memcpy(), ctx::method, OUTPUT, UINT_MAX, ZIP_CM_LZMA, ZIP_COMPRESSION_END, ZIP_COMPRESSION_ERROR, ZIP_COMPRESSION_NEED_DATA, ZIP_COMPRESSION_OK, zip_error_set(), ZIP_MIN, and ctx::zstr.

◆ start()

static bool start ( void *  ud,
zip_stat_t st,
zip_file_attributes_t attributes 
)
static

Definition at line 193 of file zip_algorithm_xz.c.

193  {
194  struct ctx *ctx = (struct ctx *)ud;
195  lzma_ret ret;
196 
198  lzma_lzma_preset(&opt_lzma, ctx->compression_flags);
199  lzma_filter filters[] = {
201  {.id = LZMA_VLI_UNKNOWN, .options = NULL},
202  };
203 
204  ctx->zstr.avail_in = 0;
205  ctx->zstr.next_in = NULL;
206  ctx->zstr.avail_out = 0;
207  ctx->zstr.next_out = NULL;
208 
209  if (ctx->compress) {
210  if (ctx->method == ZIP_CM_LZMA)
211  ret = lzma_alone_encoder(&ctx->zstr, filters[0].options);
212  else
213  ret = lzma_stream_encoder(&ctx->zstr, filters, LZMA_CHECK_CRC64);
214  }
215  else {
216  if (ctx->method == ZIP_CM_LZMA)
217  ret = lzma_alone_decoder(&ctx->zstr, UINT64_MAX);
218  else
219  ret = lzma_stream_decoder(&ctx->zstr, UINT64_MAX, LZMA_CONCATENATED);
220  }
221 
222  if (ret != LZMA_OK) {
223  zip_error_set(ctx->error, map_error(ret), 0);
224  return false;
225  }
226 
227  /* If general purpose bits 1 & 2 are both zero, write real uncompressed size in header. */
228  if ((attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) && (attributes->general_purpose_bit_mask & 0x6) == 0x6 && (attributes->general_purpose_bit_flags & 0x06) == 0 && (st->valid & ZIP_STAT_SIZE)) {
229  ctx->uncompresssed_size = st->size;
230  }
231  else {
233  }
234 
235  return true;
236 }
@ LZMA_CHECK_CRC64
Definition: check.h:42
#define LZMA_CONCATENATED
Definition: container.h:515
const lzma_filter * filters
Definition: container.h:315
#define ZIP_STAT_SIZE
Definition: zip.h:292
#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS
Definition: zip.h:333
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
#define LZMA_FILTER_LZMA2
LZMA2 Filter ID.
Definition: lzma12.h:40
#define LZMA_FILTER_LZMA1
LZMA1 Filter ID.
Definition: lzma12.h:30
#define UINT64_MAX
Filter options.
Definition: filter.h:43
void * options
Pointer to filter-specific options structure.
Definition: filter.h:63
lzma_vli id
Filter ID.
Definition: filter.h:54
Options specific to the LZMA1 and LZMA2 filters.
Definition: lzma12.h:185
zip_uint16_t general_purpose_bit_mask
Definition: zip.h:326
zip_uint16_t general_purpose_bit_flags
Definition: zip.h:325
zip_uint64_t valid
Definition: zip.h:319
zip_uint64_t valid
Definition: zip.h:301
zip_uint64_t size
Definition: zip.h:304
static lzma_options_lzma opt_lzma
#define LZMA_VLI_UNKNOWN
VLI value to denote that the value is unknown.
Definition: vli.h:39

References ctx::compress, ctx::compression_flags, ctx::error, filters, zip_file_attributes::general_purpose_bit_flags, zip_file_attributes::general_purpose_bit_mask, lzma_filter::id, LZMA_CHECK_CRC64, LZMA_CONCATENATED, LZMA_FILTER_LZMA1, LZMA_FILTER_LZMA2, LZMA_OK, LZMA_VLI_UNKNOWN, map_error(), ctx::method, NULL, opt_lzma, options, lzma_filter::options, zip_stat::size, UINT64_MAX, ctx::uncompresssed_size, zip_stat::valid, zip_file_attributes::valid, ZIP_CM_LZMA, zip_error_set(), ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS, ZIP_STAT_SIZE, ZIP_UINT64_MAX, and ctx::zstr.

Variable Documentation

◆ zip_algorithm_xz_compress

zip_compression_algorithm_t zip_algorithm_xz_compress
Initial value:
= {
20,
end,
}
static zip_uint64_t maximum_compressed_size(zip_uint64_t uncompressed_size)
static void deallocate(void *ud)
static void * compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error)
static bool start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes)
static bool end(void *ud)
static zip_uint16_t general_purpose_bit_flags(void *ud)
static void end_of_input(void *ud)
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)
static zip_compression_status_t process(void *ud, zip_uint8_t *data, zip_uint64_t *length)

Definition at line 379 of file zip_algorithm_xz.c.

◆ zip_algorithm_xz_decompress

zip_compression_algorithm_t zip_algorithm_xz_decompress
Initial value:
= {
20,
end,
}
static void * decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error)

Definition at line 393 of file zip_algorithm_xz.c.