Rizin
unix-like reverse engineering framework and cli tools
block_decoder.c File Reference

Decodes .xz Blocks. More...

#include "block_decoder.h"
#include "filter_decoder.h"
#include "check.h"

Go to the source code of this file.

Classes

struct  lzma_block_coder
 

Functions

static bool update_size (lzma_vli *size, lzma_vli add, lzma_vli limit)
 
static bool is_size_valid (lzma_vli size, lzma_vli reference)
 
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)
 
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)
 
 LZMA_API (lzma_ret)
 

Detailed Description

Decodes .xz Blocks.

Definition in file block_decoder.c.

Function Documentation

◆ block_decode()

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 
)
static

Definition at line 77 of file block_decoder.c.

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 }
@ 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
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
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
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
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_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
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.
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_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_STREAM_END
End of stream was reached.
Definition: base.h:63
@ LZMA_OK
Operation completed successfully.
Definition: base.h:58
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

References test-lz4-speed::action, allocator, lzma_block_coder::block, lzma_check_state::buffer, lzma_block::check, lzma_block_coder::check, lzma_block_coder::check_pos, lzma_next_coder_s::code, lzma_next_coder_s::coder, lzma_block_coder::compressed_limit, lzma_block::compressed_size, lzma_block_coder::compressed_size, lzma_block_coder::ignore_check, in, in_pos, in_size, is_size_valid(), lzma_bufcpy(), lzma_check_finish(), LZMA_CHECK_NONE, lzma_check_update(), LZMA_DATA_ERROR, LZMA_OK, LZMA_PROG_ERROR, LZMA_STREAM_END, lzma_block_coder::next, out, out_pos, lzma_block::raw_check, lzma_block_coder::sequence, lzma_check_state::u8, lzma_block::uncompressed_size, lzma_block_coder::uncompressed_size, and update_size().

Referenced by lzma_block_decoder_init().

◆ block_decoder_end()

static void block_decoder_end ( void *  coder_ptr,
const lzma_allocator allocator 
)
static

Definition at line 182 of file block_decoder.c.

183 {
184  lzma_block_coder *coder = coder_ptr;
185  lzma_next_end(&coder->next, allocator);
186  lzma_free(coder, allocator);
187  return;
188 }
void lzma_free(void *ptr, const lzma_allocator *allocator)
Frees memory.
Definition: common.c:78
void lzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator)
Definition: common.c:145

References allocator, lzma_free(), lzma_next_end(), and lzma_block_coder::next.

Referenced by lzma_block_decoder_init().

◆ is_size_valid()

static bool is_size_valid ( lzma_vli  size,
lzma_vli  reference 
)
inlinestatic

Definition at line 70 of file block_decoder.c.

71 {
72  return reference == LZMA_VLI_UNKNOWN || reference == size;
73 }
voidpf void uLong size
Definition: ioapi.h:138
#define LZMA_VLI_UNKNOWN
VLI value to denote that the value is unknown.
Definition: vli.h:39

References LZMA_VLI_UNKNOWN.

Referenced by block_decode().

◆ LZMA_API()

LZMA_API ( lzma_ret  )

Definition at line 248 of file block_decoder.c.

250 {
252 
255 
256  return LZMA_OK;
257 }
lzma_ret lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, lzma_block *block)
static lzma_stream strm
Definition: full_flush.c:20
bool supported_actions[LZMA_ACTION_MAX+1]
Indicates which lzma_action values are allowed by next.code.
Definition: common.h:220
lzma_internal * internal
Definition: base.h:505
#define lzma_next_strm_init(func, strm,...)
Definition: common.h:303
@ LZMA_FINISH
Finish the coding operation.
Definition: base.h:328
@ LZMA_RUN
Continue coding.
Definition: base.h:251

References lzma_stream::internal, lzma_block_decoder_init(), LZMA_FINISH, lzma_next_strm_init, LZMA_OK, LZMA_RUN, strm, and lzma_internal_s::supported_actions.

◆ lzma_block_decoder_init()

lzma_ret lzma_block_decoder_init ( lzma_next_coder next,
const lzma_allocator allocator,
lzma_block block 
)

Definition at line 192 of file block_decoder.c.

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 }
static void block_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
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
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)
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
uint32_t version
Block format version.
Definition: block.h:52
lzma_end_function end
Definition: common.h:155
#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
void * lzma_alloc(size_t size, const lzma_allocator *allocator) lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
Allocates memory.
#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_MAX
Maximum supported value of a variable-length integer.
Definition: vli.h:34
@ LZMA_MEM_ERROR
Cannot allocate memory.
Definition: base.h:128

References allocator, lzma_block_coder::block, block_decode(), block_decoder_end(), lzma_block::check, lzma_block_coder::check, lzma_block_coder::check_pos, lzma_next_coder_s::code, lzma_next_coder_s::coder, lzma_block_coder::compressed_limit, lzma_block::compressed_size, lzma_block_coder::compressed_size, lzma_next_coder_s::end, lzma_block::filters, lzma_block::header_size, lzma_block::ignore_check, lzma_block_coder::ignore_check, lzma_alloc(), lzma_check_init(), LZMA_MEM_ERROR, LZMA_NEXT_CODER_INIT, lzma_next_coder_init, LZMA_PROG_ERROR, lzma_raw_decoder_init(), LZMA_VLI_C, lzma_vli_is_valid, LZMA_VLI_MAX, LZMA_VLI_UNKNOWN, lzma_block_coder::next, NULL, lzma_block_coder::sequence, lzma_block::uncompressed_size, lzma_block_coder::uncompressed_size, and lzma_block::version.

Referenced by LZMA_API(), and stream_decode().

◆ update_size()

static bool update_size ( lzma_vli size,
lzma_vli  add,
lzma_vli  limit 
)
inlinestatic

Definition at line 55 of file block_decoder.c.

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 }
static uint32_t const uint8_t uint32_t uint32_t limit
Definition: memcmplen.h:45
static int add(char *argv[])
Definition: ziptool.c:84

References add(), limit, and LZMA_VLI_MAX.

Referenced by block_decode().