Rizin
unix-like reverse engineering framework and cli tools
stream_buffer_encoder.c
Go to the documentation of this file.
1 //
5 //
6 // Author: Lasse Collin
7 //
8 // This file has been put into the public domain.
9 // You can do whatever you want with this file.
10 //
12 
13 #include "index.h"
14 
15 
19 #define INDEX_BOUND ((1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 4 + 3) & ~3)
20 
22 #define HEADERS_BOUND (2 * LZMA_STREAM_HEADER_SIZE + INDEX_BOUND)
23 
24 
25 extern LZMA_API(size_t)
26 lzma_stream_buffer_bound(size_t uncompressed_size)
27 {
28  // Get the maximum possible size of a Block.
29  const size_t block_bound = lzma_block_buffer_bound(uncompressed_size);
30  if (block_bound == 0)
31  return 0;
32 
33  // Catch the possible integer overflow and also prevent the size of
34  // the Stream exceeding LZMA_VLI_MAX (theoretically possible on
35  // 64-bit systems).
36  if (my_min(SIZE_MAX, LZMA_VLI_MAX) - block_bound < HEADERS_BOUND)
37  return 0;
38 
39  return block_bound + HEADERS_BOUND;
40 }
41 
42 
44 lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
46  const uint8_t *in, size_t in_size,
47  uint8_t *out, size_t *out_pos_ptr, size_t out_size)
48 {
49  // Sanity checks
50  if (filters == NULL || (unsigned int)(check) > LZMA_CHECK_ID_MAX
51  || (in == NULL && in_size != 0) || out == NULL
52  || out_pos_ptr == NULL || *out_pos_ptr > out_size)
53  return LZMA_PROG_ERROR;
54 
55  if (!lzma_check_is_supported(check))
57 
58  // Note for the paranoids: Index encoder prevents the Stream from
59  // getting too big and still being accepted with LZMA_OK, and Block
60  // encoder catches if the input is too big. So we don't need to
61  // separately check if the buffers are too big.
62 
63  // Use a local copy. We update *out_pos_ptr only if everything
64  // succeeds.
65  size_t out_pos = *out_pos_ptr;
66 
67  // Check that there's enough space for both Stream Header and
68  // Stream Footer.
69  if (out_size - out_pos <= 2 * LZMA_STREAM_HEADER_SIZE)
70  return LZMA_BUF_ERROR;
71 
72  // Reserve space for Stream Footer so we don't need to check for
73  // available space again before encoding Stream Footer.
74  out_size -= LZMA_STREAM_HEADER_SIZE;
75 
76  // Encode the Stream Header.
77  lzma_stream_flags stream_flags = {
78  .version = 0,
79  .check = check,
80  };
81 
82  if (lzma_stream_header_encode(&stream_flags, out + out_pos)
83  != LZMA_OK)
84  return LZMA_PROG_ERROR;
85 
87 
88  // Encode a Block but only if there is at least one byte of input.
89  lzma_block block = {
90  .version = 0,
91  .check = check,
92  .filters = filters,
93  };
94 
95  if (in_size > 0)
96  return_if_error(lzma_block_buffer_encode(&block, allocator,
97  in, in_size, out, &out_pos, out_size));
98 
99  // Index
100  {
101  // Create an Index. It will have one Record if there was
102  // at least one byte of input to encode. Otherwise the
103  // Index will be empty.
104  lzma_index *i = lzma_index_init(allocator);
105  if (i == NULL)
106  return LZMA_MEM_ERROR;
107 
108  lzma_ret ret = LZMA_OK;
109 
110  if (in_size > 0)
111  ret = lzma_index_append(i, allocator,
112  lzma_block_unpadded_size(&block),
113  block.uncompressed_size);
114 
115  // If adding the Record was successful, encode the Index
116  // and get its size which will be stored into Stream Footer.
117  if (ret == LZMA_OK) {
118  ret = lzma_index_buffer_encode(
119  i, out, &out_pos, out_size);
120 
121  stream_flags.backward_size = lzma_index_size(i);
122  }
123 
124  lzma_index_end(i, allocator);
125 
126  if (ret != LZMA_OK)
127  return ret;
128  }
129 
130  // Stream Footer. We have already reserved space for this.
131  if (lzma_stream_footer_encode(&stream_flags, out + out_pos)
132  != LZMA_OK)
133  return LZMA_PROG_ERROR;
134 
136 
137  // Everything went fine, make the new output position available
138  // to the application.
139  *out_pos_ptr = out_pos;
140  return LZMA_OK;
141 }
lzma_check
Type of the integrity check (Check ID)
Definition: check.h:27
#define LZMA_CHECK_ID_MAX
Maximum valid Check ID.
Definition: check.h:68
lzma_index ** i
Definition: index.h:629
const lzma_allocator const uint8_t size_t uint8_t size_t * out_pos
Definition: block.h:528
const lzma_allocator const uint8_t size_t in_size
Definition: block.h:527
const lzma_allocator * allocator
Definition: block.h:377
const lzma_allocator const uint8_t * in
Definition: block.h:527
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
Handling of Index.
lzma_check check
Definition: container.h:292
const lzma_filter * filters
Definition: container.h:315
#define NULL
Definition: cris-opc.c:27
unsigned char uint8_t
Definition: sftypes.h:31
#define SIZE_MAX
LZMA_API(size_t)
Calculate maximum output size for single-call Block encoding.
#define HEADERS_BOUND
Stream Header, Stream Footer, and Index.
#define LZMA_STREAM_HEADER_SIZE
Size of Stream Header and Stream Footer.
Definition: stream_flags.h:27
Custom functions for memory handling.
Definition: base.h:372
Options for the Block and Block Header encoders and decoders.
Definition: block.h:30
lzma_vli uncompressed_size
Uncompressed Size in bytes.
Definition: block.h:172
uint32_t version
Block format version.
Definition: block.h:52
Filter options.
Definition: filter.h:43
Options for encoding/decoding Stream Header and Stream Footer.
Definition: stream_flags.h:33
uint32_t version
Stream Flags format version.
Definition: stream_flags.h:51
lzma_vli backward_size
Backward Size.
Definition: stream_flags.h:69
#define return_if_error(expr)
Return if expression doesn't evaluate to LZMA_OK.
Definition: common.h:278
uint64_t uncompressed_size
Definition: list.c:106
#define my_min(x, y)
Definition: sysdefs.h:185
#define LZMA_VLI_MAX
Maximum supported value of a variable-length integer.
Definition: vli.h:34
lzma_ret
Return values used by several functions in liblzma.
Definition: base.h:57
@ LZMA_PROG_ERROR
Programming error.
Definition: base.h:218
@ LZMA_MEM_ERROR
Cannot allocate memory.
Definition: base.h:128
@ LZMA_UNSUPPORTED_CHECK
Cannot calculate the integrity check.
Definition: base.h:90
@ LZMA_BUF_ERROR
No progress is possible.
Definition: base.h:191
@ LZMA_OK
Operation completed successfully.
Definition: base.h:58