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

Filter-specific stuff common for both encoder and decoder. More...

#include "filter_common.h"

Go to the source code of this file.

Functions

 LZMA_API (lzma_ret)
 
static lzma_ret validate_chain (const lzma_filter *filters, size_t *count)
 
lzma_ret lzma_raw_coder_init (lzma_next_coder *next, const lzma_allocator *allocator, const lzma_filter *options, lzma_filter_find coder_find, bool is_encoder)
 
uint64_t lzma_raw_coder_memusage (lzma_filter_find coder_find, const lzma_filter *filters)
 

Variables

struct {
   lzma_vli   id
 Filter ID. More...
 
   size_t   options_size
 Size of the filter-specific options structure. More...
 
   bool   non_last_ok
 
   bool   last_ok
 
   bool   changes_size
 
features []
 

Detailed Description

Filter-specific stuff common for both encoder and decoder.

Definition in file filter_common.c.

Function Documentation

◆ LZMA_API()

LZMA_API ( lzma_ret  )

Definition at line 124 of file filter_common.c.

127 {
128  if (src == NULL || dest == NULL)
129  return LZMA_PROG_ERROR;
130 
131  lzma_ret ret;
132  size_t i;
133  for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) {
134  // There must be a maximum of four filters plus
135  // the array terminator.
136  if (i == LZMA_FILTERS_MAX) {
137  ret = LZMA_OPTIONS_ERROR;
138  goto error;
139  }
140 
141  dest[i].id = src[i].id;
142 
143  if (src[i].options == NULL) {
144  dest[i].options = NULL;
145  } else {
146  // See if the filter is supported only when the
147  // options is not NULL. This might be convenient
148  // sometimes if the app is actually copying only
149  // a partial filter chain with a place holder ID.
150  //
151  // When options is not NULL, the Filter ID must be
152  // supported by us, because otherwise we don't know
153  // how big the options are.
154  size_t j;
155  for (j = 0; src[i].id != features[j].id; ++j) {
156  if (features[j].id == LZMA_VLI_UNKNOWN) {
157  ret = LZMA_OPTIONS_ERROR;
158  goto error;
159  }
160  }
161 
162  // Allocate and copy the options.
163  dest[i].options = lzma_alloc(features[j].options_size,
164  allocator);
165  if (dest[i].options == NULL) {
166  ret = LZMA_MEM_ERROR;
167  goto error;
168  }
169 
172  }
173  }
174 
175  // Terminate the filter array.
176  assert(i <= LZMA_FILTERS_MAX + 1);
177  dest[i].id = LZMA_VLI_UNKNOWN;
178  dest[i].options = NULL;
179 
180  return LZMA_OK;
181 
182 error:
183  // Free the options which we have already allocated.
184  while (i-- > 0) {
186  dest[i].options = NULL;
187  }
188 
189  return ret;
190 }
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
const lzma_allocator * allocator
Definition: block.h:377
#define NULL
Definition: cris-opc.c:27
#define LZMA_FILTERS_MAX
Maximum number of filters in a chain.
Definition: filter.h:26
static const struct @646 features[]
size_t options_size
Size of the filter-specific options structure.
Definition: filter_common.c:21
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
char * dest
Definition: lz4.h:697
assert(limit<=UINT32_MAX/2)
void * lzma_alloc(size_t size, const lzma_allocator *allocator) lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
Allocates memory.
void error(const char *msg)
Definition: untgz.c:593
#define LZMA_VLI_UNKNOWN
VLI value to denote that the value is unknown.
Definition: vli.h:39
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_OPTIONS_ERROR
Invalid or unsupported options.
Definition: base.h:160
@ LZMA_OK
Operation completed successfully.
Definition: base.h:58
void lzma_free(void *ptr, const lzma_allocator *allocator)
Frees memory.
Definition: common.c:78

References allocator, assert(), dest, error(), features, i, lzma_alloc(), LZMA_FILTERS_MAX, lzma_free(), LZMA_MEM_ERROR, LZMA_OK, LZMA_OPTIONS_ERROR, LZMA_PROG_ERROR, LZMA_VLI_UNKNOWN, memcpy(), NULL, options, options_size, and src.

◆ lzma_raw_coder_init()

lzma_ret lzma_raw_coder_init ( lzma_next_coder next,
const lzma_allocator allocator,
const lzma_filter options,
lzma_filter_find  coder_find,
bool  is_encoder 
)

Definition at line 242 of file filter_common.c.

245 {
246  // Do some basic validation and get the number of filters.
247  size_t count;
249 
250  // Set the filter functions and copy the options pointer.
252  if (is_encoder) {
253  for (size_t i = 0; i < count; ++i) {
254  // The order of the filters is reversed in the
255  // encoder. It allows more efficient handling
256  // of the uncompressed data.
257  const size_t j = count - i - 1;
258 
259  const lzma_filter_coder *const fc
260  = coder_find(options[i].id);
261  if (fc == NULL || fc->init == NULL)
262  return LZMA_OPTIONS_ERROR;
263 
264  filters[j].id = options[i].id;
265  filters[j].init = fc->init;
266  filters[j].options = options[i].options;
267  }
268  } else {
269  for (size_t i = 0; i < count; ++i) {
270  const lzma_filter_coder *const fc
271  = coder_find(options[i].id);
272  if (fc == NULL || fc->init == NULL)
273  return LZMA_OPTIONS_ERROR;
274 
275  filters[i].id = options[i].id;
276  filters[i].init = fc->init;
277  filters[i].options = options[i].options;
278  }
279  }
280 
281  // Terminate the array.
283  filters[count].init = NULL;
284 
285  // Initialize the filters.
286  const lzma_ret ret = lzma_next_filter_init(next, allocator, filters);
287  if (ret != LZMA_OK)
288  lzma_next_end(next, allocator);
289 
290  return ret;
291 }
const lzma_filter * filters
Definition: container.h:315
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 count
Definition: sflib.h:98
static lzma_ret validate_chain(const lzma_filter *filters, size_t *count)
Both lzma_filter_encoder and lzma_filter_decoder begin with these members.
Definition: filter_common.h:20
lzma_init_function init
Definition: filter_common.h:26
void * options
Pointer to filter-specific options structure.
Definition: filter.h:63
lzma_vli id
Filter ID.
Definition: filter.h:54
#define return_if_error(expr)
Return if expression doesn't evaluate to LZMA_OK.
Definition: common.h:278
lzma_ret lzma_next_filter_init(lzma_next_coder *next, const lzma_allocator *allocator, const lzma_filter_info *filters)
Definition: common.c:116
void lzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator)
Definition: common.c:145

References allocator, count, filters, i, lzma_filter::id, lzma_filter_coder::init, LZMA_FILTERS_MAX, lzma_next_end(), lzma_next_filter_init(), LZMA_OK, LZMA_OPTIONS_ERROR, LZMA_VLI_UNKNOWN, NULL, options, lzma_filter::options, return_if_error, and validate_chain().

Referenced by lzma_raw_decoder_init(), and lzma_raw_encoder_init().

◆ lzma_raw_coder_memusage()

uint64_t lzma_raw_coder_memusage ( lzma_filter_find  coder_find,
const lzma_filter filters 
)

Definition at line 295 of file filter_common.c.

297 {
298  // The chain has to have at least one filter.
299  {
300  size_t tmp;
301  if (validate_chain(filters, &tmp) != LZMA_OK)
302  return UINT64_MAX;
303  }
304 
305  uint64_t total = 0;
306  size_t i = 0;
307 
308  do {
309  const lzma_filter_coder *const fc
310  = coder_find(filters[i].id);
311  if (fc == NULL)
312  return UINT64_MAX; // Unsupported Filter ID
313 
314  if (fc->memusage == NULL) {
315  // This filter doesn't have a function to calculate
316  // the memory usage and validate the options. Such
317  // filters need only little memory, so we use 1 KiB
318  // as a good estimate. They also accept all possible
319  // options, so there's no need to worry about lack
320  // of validation.
321  total += 1024;
322  } else {
323  // Call the filter-specific memory usage calculation
324  // function.
325  const uint64_t usage
326  = fc->memusage(filters[i].options);
327  if (usage == UINT64_MAX)
328  return UINT64_MAX; // Invalid options
329 
330  total += usage;
331  }
332  } while (filters[++i].id != LZMA_VLI_UNKNOWN);
333 
334  // Add some fixed amount of extra. It's to compensate memory usage
335  // of Stream, Block etc. coders, malloc() overhead, stack etc.
336  return total + LZMA_MEMUSAGE_BASE;
337 }
void usage(const char *message)
unsigned long uint64_t
Definition: sftypes.h:28
#define UINT64_MAX
uint64_t(* memusage)(const void *options)
Definition: filter_common.h:30
#define LZMA_MEMUSAGE_BASE
Definition: common.h:63

References filters, i, LZMA_MEMUSAGE_BASE, LZMA_OK, LZMA_VLI_UNKNOWN, lzma_filter_coder::memusage, NULL, options, autogen_x86imm::tmp, UINT64_MAX, usage(), and validate_chain().

Referenced by LZMA_API().

◆ validate_chain()

static lzma_ret validate_chain ( const lzma_filter filters,
size_t count 
)
static

Definition at line 194 of file filter_common.c.

195 {
196  // There must be at least one filter.
197  if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN)
198  return LZMA_PROG_ERROR;
199 
200  // Number of non-last filters that may change the size of the data
201  // significantly (that is, more than 1-2 % or so).
202  size_t changes_size_count = 0;
203 
204  // True if it is OK to add a new filter after the current filter.
205  bool non_last_ok = true;
206 
207  // True if the last filter in the given chain is actually usable as
208  // the last filter. Only filters that support embedding End of Payload
209  // Marker can be used as the last filter in the chain.
210  bool last_ok = false;
211 
212  size_t i = 0;
213  do {
214  size_t j;
215  for (j = 0; filters[i].id != features[j].id; ++j)
216  if (features[j].id == LZMA_VLI_UNKNOWN)
217  return LZMA_OPTIONS_ERROR;
218 
219  // If the previous filter in the chain cannot be a non-last
220  // filter, the chain is invalid.
221  if (!non_last_ok)
222  return LZMA_OPTIONS_ERROR;
223 
224  non_last_ok = features[j].non_last_ok;
225  last_ok = features[j].last_ok;
226  changes_size_count += features[j].changes_size;
227 
228  } while (filters[++i].id != LZMA_VLI_UNKNOWN);
229 
230  // There must be 1-4 filters. The last filter must be usable as
231  // the last filter in the chain. A maximum of three filters are
232  // allowed to change the size of the data.
233  if (i > LZMA_FILTERS_MAX || !last_ok || changes_size_count > 3)
234  return LZMA_OPTIONS_ERROR;
235 
236  *count = i;
237  return LZMA_OK;
238 }
bool last_ok
Definition: filter_common.c:29
bool non_last_ok
Definition: filter_common.c:25

References count, features, filters, i, lzma_filter::id, last_ok, LZMA_FILTERS_MAX, LZMA_OK, LZMA_OPTIONS_ERROR, LZMA_PROG_ERROR, LZMA_VLI_UNKNOWN, non_last_ok, and NULL.

Referenced by lzma_raw_coder_init(), and lzma_raw_coder_memusage().

Variable Documentation

◆ changes_size

bool changes_size

True if the filter may change the size of the data (that is, the amount of encoded output can be different than the amount of uncompressed input).

Definition at line 34 of file filter_common.c.

◆ 

◆ id

Filter ID.

Definition at line 18 of file filter_common.c.

◆ last_ok

bool last_ok

True if it is OK to use this filter as the last filter in the chain.

Definition at line 29 of file filter_common.c.

Referenced by validate_chain().

◆ non_last_ok

bool non_last_ok

True if it is OK to use this filter as non-last filter in the chain.

Definition at line 25 of file filter_common.c.

Referenced by validate_chain().

◆ options_size

size_t options_size

Size of the filter-specific options structure.

Definition at line 21 of file filter_common.c.

Referenced by LZMA_API().