Rizin
unix-like reverse engineering framework and cli tools
block_decoder.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 "block_decoder.h"
14 #include "filter_decoder.h"
15 #include "check.h"
16 
17 
18 typedef struct {
19  enum {
23  } sequence;
24 
27 
31 
34 
37 
42 
44  size_t check_pos;
45 
48 
52 
53 
54 static inline bool
56 {
57  if (limit > LZMA_VLI_MAX)
59 
60  if (limit < *size || limit - *size < add)
61  return true;
62 
63  *size += add;
64 
65  return false;
66 }
67 
68 
69 static inline bool
71 {
72  return reference == LZMA_VLI_UNKNOWN || reference == size;
73 }
74 
75 
76 static lzma_ret
77 block_decode(void *coder_ptr, const lzma_allocator *allocator,
78  const uint8_t *restrict in, size_t *restrict in_pos,
79  size_t in_size, uint8_t *restrict out,
80  size_t *restrict out_pos, size_t out_size, lzma_action action)
81 {
82  lzma_block_coder *coder = coder_ptr;
83 
84  switch (coder->sequence) {
85  case SEQ_CODE: {
86  const size_t in_start = *in_pos;
87  const size_t out_start = *out_pos;
88 
89  const lzma_ret ret = coder->next.code(coder->next.coder,
91  out, out_pos, out_size, action);
92 
93  const size_t in_used = *in_pos - in_start;
94  const size_t out_used = *out_pos - out_start;
95 
96  // NOTE: We compare to compressed_limit here, which prevents
97  // the total size of the Block growing past LZMA_VLI_MAX.
98  if (update_size(&coder->compressed_size, in_used,
99  coder->compressed_limit)
100  || update_size(&coder->uncompressed_size,
101  out_used,
102  coder->block->uncompressed_size))
103  return LZMA_DATA_ERROR;
104 
105  if (!coder->ignore_check)
106  lzma_check_update(&coder->check, coder->block->check,
107  out + out_start, out_used);
108 
109  if (ret != LZMA_STREAM_END)
110  return ret;
111 
112  // Compressed and Uncompressed Sizes are now at their final
113  // values. Verify that they match the values given to us.
114  if (!is_size_valid(coder->compressed_size,
115  coder->block->compressed_size)
116  || !is_size_valid(coder->uncompressed_size,
117  coder->block->uncompressed_size))
118  return LZMA_DATA_ERROR;
119 
120  // Copy the values into coder->block. The caller
121  // may use this information to construct Index.
122  coder->block->compressed_size = coder->compressed_size;
123  coder->block->uncompressed_size = coder->uncompressed_size;
124 
125  coder->sequence = SEQ_PADDING;
126  }
127 
128  // Fall through
129 
130  case SEQ_PADDING:
131  // Compressed Data is padded to a multiple of four bytes.
132  while (coder->compressed_size & 3) {
133  if (*in_pos >= in_size)
134  return LZMA_OK;
135 
136  // We use compressed_size here just get the Padding
137  // right. The actual Compressed Size was stored to
138  // coder->block already, and won't be modified by
139  // us anymore.
140  ++coder->compressed_size;
141 
142  if (in[(*in_pos)++] != 0x00)
143  return LZMA_DATA_ERROR;
144  }
145 
146  if (coder->block->check == LZMA_CHECK_NONE)
147  return LZMA_STREAM_END;
148 
149  if (!coder->ignore_check)
150  lzma_check_finish(&coder->check, coder->block->check);
151 
152  coder->sequence = SEQ_CHECK;
153 
154  // Fall through
155 
156  case SEQ_CHECK: {
157  const size_t check_size = lzma_check_size(coder->block->check);
159  &coder->check_pos, check_size);
160  if (coder->check_pos < check_size)
161  return LZMA_OK;
162 
163  // Validate the Check only if we support it.
164  // coder->check.buffer may be uninitialized
165  // when the Check ID is not supported.
166  if (!coder->ignore_check
167  && lzma_check_is_supported(coder->block->check)
168  && memcmp(coder->block->raw_check,
169  coder->check.buffer.u8,
170  check_size) != 0)
171  return LZMA_DATA_ERROR;
172 
173  return LZMA_STREAM_END;
174  }
175  }
176 
177  return LZMA_PROG_ERROR;
178 }
179 
180 
181 static void
183 {
184  lzma_block_coder *coder = coder_ptr;
185  lzma_next_end(&coder->next, allocator);
186  lzma_free(coder, allocator);
187  return;
188 }
189 
190 
191 extern lzma_ret
193  lzma_block *block)
194 {
196 
197  // Validate the options. lzma_block_unpadded_size() does that for us
198  // except for Uncompressed Size and filters. Filters are validated
199  // by the raw decoder.
200  if (lzma_block_unpadded_size(block) == 0
202  return LZMA_PROG_ERROR;
203 
204  // Allocate *next->coder if needed.
205  lzma_block_coder *coder = next->coder;
206  if (coder == NULL) {
207  coder = lzma_alloc(sizeof(lzma_block_coder), allocator);
208  if (coder == NULL)
209  return LZMA_MEM_ERROR;
210 
211  next->coder = coder;
212  next->code = &block_decode;
213  next->end = &block_decoder_end;
214  coder->next = LZMA_NEXT_CODER_INIT;
215  }
216 
217  // Basic initializations
218  coder->sequence = SEQ_CODE;
219  coder->block = block;
220  coder->compressed_size = 0;
221  coder->uncompressed_size = 0;
222 
223  // If Compressed Size is not known, we calculate the maximum allowed
224  // value so that encoded size of the Block (including Block Padding)
225  // is still a valid VLI and a multiple of four.
226  coder->compressed_limit
228  ? (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
229  - block->header_size
230  - lzma_check_size(block->check)
231  : block->compressed_size;
232 
233  // Initialize the check. It's caller's problem if the Check ID is not
234  // supported, and the Block decoder cannot verify the Check field.
235  // Caller can test lzma_check_is_supported(block->check).
236  coder->check_pos = 0;
237  lzma_check_init(&coder->check, block->check);
238 
239  coder->ignore_check = block->version >= 1
240  ? block->ignore_check : false;
241 
242  // Initialize the filter chain.
243  return lzma_raw_decoder_init(&coder->next, allocator,
244  block->filters);
245 }
246 
247 
249 lzma_block_decoder(lzma_stream *strm, lzma_block *block)
250 {
252 
255 
256  return LZMA_OK;
257 }
@ LZMA_CHECK_NONE
Definition: check.h:28
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_pos
Definition: block.h:579
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
LZMA_API(lzma_ret)
static void block_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
lzma_ret lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, lzma_block *block)
static bool update_size(lzma_vli *size, lzma_vli add, lzma_vli limit)
Definition: block_decoder.c:55
static bool is_size_valid(lzma_vli size, lzma_vli reference)
Definition: block_decoder.c:70
static lzma_ret block_decode(void *coder_ptr, const lzma_allocator *allocator, const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size, uint8_t *restrict out, size_t *restrict out_pos, size_t out_size, lzma_action action)
Definition: block_decoder.c:77
Decodes .xz Blocks.
void lzma_check_finish(lzma_check_state *check, lzma_check type)
Finish the check calculation and store the result to check->buffer.u8.
Definition: check.c:148
void lzma_check_update(lzma_check_state *check, lzma_check type, const uint8_t *buf, size_t size)
Update the check state.
Definition: check.c:117
void lzma_check_init(lzma_check_state *check, lzma_check type)
Initialize *check depending on type.
Definition: check.c:84
#define NULL
Definition: cris-opc.c:27
lzma_ret lzma_raw_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, const lzma_filter *options)
Filter ID mapping to filter-specific functions.
static lzma_stream strm
Definition: full_flush.c:20
voidpf void uLong size
Definition: ioapi.h:138
#define restrict
static uint32_t const uint8_t uint32_t uint32_t limit
Definition: memcmplen.h:45
unsigned char uint8_t
Definition: sftypes.h:31
Custom functions for memory handling.
Definition: base.h:372
lzma_check_state check
Check of the uncompressed data.
Definition: block_decoder.c:47
size_t check_pos
Position when reading the Check field.
Definition: block_decoder.c:44
enum lzma_block_coder::@643 sequence
lzma_next_coder next
The filters in the chain; initialized with lzma_raw_decoder_init().
Definition: block_decoder.c:26
bool ignore_check
True if the integrity check won't be calculated and verified.
Definition: block_decoder.c:50
lzma_block * block
Definition: block_decoder.c:30
lzma_vli uncompressed_size
Uncompressed Size calculated while decoding.
Definition: block_decoder.c:36
lzma_vli compressed_size
Compressed Size calculated while decoding.
Definition: block_decoder.c:33
lzma_vli compressed_limit
Definition: block_decoder.c:41
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
uint8_t raw_check[LZMA_CHECK_SIZE_MAX]
Raw value stored in the Check field.
Definition: block.h:217
lzma_bool ignore_check
A flag to Block decoder to not verify the Check field.
Definition: block.h:261
lzma_filter * filters
Array of filters.
Definition: block.h:200
uint32_t header_size
Size of the Block Header field.
Definition: block.h:72
lzma_check check
Type of integrity Check.
Definition: block.h:93
lzma_vli compressed_size
Size of the Compressed Data in bytes.
Definition: block.h:148
uint32_t version
Block format version.
Definition: block.h:52
Structure to hold internal state of the check being calculated.
Definition: check.h:81
uint8_t u8[64]
Definition: check.h:84
union lzma_check_state::@638 buffer
Buffer to hold the final result and a temporary buffer for SHA256.
bool supported_actions[LZMA_ACTION_MAX+1]
Indicates which lzma_action values are allowed by next.code.
Definition: common.h:220
Hold data and function pointers of the next filter in the chain.
Definition: common.h:135
lzma_code_function code
Pointer to function to do the actual coding.
Definition: common.h:150
void * coder
Pointer to coder-specific data.
Definition: common.h:137
lzma_end_function end
Definition: common.h:155
Passing data to and from liblzma.
Definition: base.h:485
lzma_internal * internal
Definition: base.h:505
#define LZMA_NEXT_CODER_INIT
Macro to initialize lzma_next_coder structure.
Definition: common.h:180
#define lzma_next_coder_init(func, next, allocator)
Definition: common.h:291
#define lzma_next_strm_init(func, strm,...)
Definition: common.h:303
void * lzma_alloc(size_t size, const lzma_allocator *allocator) lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
Allocates memory.
uint64_t lzma_vli
Variable-length integer type.
Definition: vli.h:63
#define LZMA_VLI_C(n)
VLI constant suffix.
Definition: vli.h:49
#define lzma_vli_is_valid(vli)
Validate a variable-length integer.
Definition: vli.h:75
#define LZMA_VLI_UNKNOWN
VLI value to denote that the value is unknown.
Definition: vli.h:39
#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_DATA_ERROR
Data is corrupt.
Definition: base.h:172
@ LZMA_MEM_ERROR
Cannot allocate memory.
Definition: base.h:128
@ LZMA_STREAM_END
End of stream was reached.
Definition: base.h:63
@ LZMA_OK
Operation completed successfully.
Definition: base.h:58
lzma_action
The ‘action’ argument for lzma_code()
Definition: base.h:250
@ LZMA_FINISH
Finish the coding operation.
Definition: base.h:328
@ LZMA_RUN
Continue coding.
Definition: base.h:251
void lzma_free(void *ptr, const lzma_allocator *allocator)
Frees memory.
Definition: common.c:78
size_t lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size, uint8_t *restrict out, size_t *restrict out_pos, size_t out_size)
Definition: common.c:94
void lzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator)
Definition: common.c:145
static int add(char *argv[])
Definition: ziptool.c:84