Rizin
unix-like reverse engineering framework and cli tools
index_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_encoder.h"
14 #include "index.h"
15 #include "check.h"
16 
17 
18 typedef struct {
19  enum {
20  SEQ_INDICATOR,
21  SEQ_COUNT,
22  SEQ_UNPADDED,
23  SEQ_UNCOMPRESSED,
25  SEQ_PADDING,
26  SEQ_CRC32,
27  } sequence;
28 
30  const lzma_index *index;
31 
34 
36  size_t pos;
37 
41 
42 
43 static lzma_ret
44 index_encode(void *coder_ptr,
45  const lzma_allocator *allocator lzma_attribute((__unused__)),
46  const uint8_t *restrict in lzma_attribute((__unused__)),
47  size_t *restrict in_pos lzma_attribute((__unused__)),
48  size_t in_size lzma_attribute((__unused__)),
50  size_t out_size,
51  lzma_action action lzma_attribute((__unused__)))
52 {
53  lzma_index_coder *coder = coder_ptr;
54 
55  // Position where to start calculating CRC32. The idea is that we
56  // need to call lzma_crc32() only once per call to index_encode().
57  const size_t out_start = *out_pos;
58 
59  // Return value to use if we return at the end of this function.
60  // We use "goto out" to jump out of the while-switch construct
61  // instead of returning directly, because that way we don't need
62  // to copypaste the lzma_crc32() call to many places.
63  lzma_ret ret = LZMA_OK;
64 
65  while (*out_pos < out_size)
66  switch (coder->sequence) {
67  case SEQ_INDICATOR:
68  out[*out_pos] = 0x00;
69  ++*out_pos;
70  coder->sequence = SEQ_COUNT;
71  break;
72 
73  case SEQ_COUNT: {
74  const lzma_vli count = lzma_index_block_count(coder->index);
75  ret = lzma_vli_encode(count, &coder->pos,
76  out, out_pos, out_size);
77  if (ret != LZMA_STREAM_END)
78  goto out;
79 
80  ret = LZMA_OK;
81  coder->pos = 0;
82  coder->sequence = SEQ_NEXT;
83  break;
84  }
85 
86  case SEQ_NEXT:
87  if (lzma_index_iter_next(
88  &coder->iter, LZMA_INDEX_ITER_BLOCK)) {
89  // Get the size of the Index Padding field.
90  coder->pos = lzma_index_padding_size(coder->index);
91  assert(coder->pos <= 3);
92  coder->sequence = SEQ_PADDING;
93  break;
94  }
95 
96  coder->sequence = SEQ_UNPADDED;
97 
98  // Fall through
99 
100  case SEQ_UNPADDED:
101  case SEQ_UNCOMPRESSED: {
102  const lzma_vli size = coder->sequence == SEQ_UNPADDED
103  ? coder->iter.block.unpadded_size
104  : coder->iter.block.uncompressed_size;
105 
106  ret = lzma_vli_encode(size, &coder->pos,
107  out, out_pos, out_size);
108  if (ret != LZMA_STREAM_END)
109  goto out;
110 
111  ret = LZMA_OK;
112  coder->pos = 0;
113 
114  // Advance to SEQ_UNCOMPRESSED or SEQ_NEXT.
115  ++coder->sequence;
116  break;
117  }
118 
119  case SEQ_PADDING:
120  if (coder->pos > 0) {
121  --coder->pos;
122  out[(*out_pos)++] = 0x00;
123  break;
124  }
125 
126  // Finish the CRC32 calculation.
127  coder->crc32 = lzma_crc32(out + out_start,
128  *out_pos - out_start, coder->crc32);
129 
130  coder->sequence = SEQ_CRC32;
131 
132  // Fall through
133 
134  case SEQ_CRC32:
135  // We don't use the main loop, because we don't want
136  // coder->crc32 to be touched anymore.
137  do {
138  if (*out_pos == out_size)
139  return LZMA_OK;
140 
141  out[*out_pos] = (coder->crc32 >> (coder->pos * 8))
142  & 0xFF;
143  ++*out_pos;
144 
145  } while (++coder->pos < 4);
146 
147  return LZMA_STREAM_END;
148 
149  default:
150  assert(0);
151  return LZMA_PROG_ERROR;
152  }
153 
154 out:
155  // Update the CRC32.
156  coder->crc32 = lzma_crc32(out + out_start,
157  *out_pos - out_start, coder->crc32);
158 
159  return ret;
160 }
161 
162 
163 static void
165 {
166  lzma_free(coder, allocator);
167  return;
168 }
169 
170 
171 static void
173 {
174  lzma_index_iter_init(&coder->iter, i);
175 
176  coder->sequence = SEQ_INDICATOR;
177  coder->index = i;
178  coder->pos = 0;
179  coder->crc32 = 0;
180 
181  return;
182 }
183 
184 
185 extern lzma_ret
187  const lzma_index *i)
188 {
190 
191  if (i == NULL)
192  return LZMA_PROG_ERROR;
193 
194  if (next->coder == NULL) {
195  next->coder = lzma_alloc(sizeof(lzma_index_coder), allocator);
196  if (next->coder == NULL)
197  return LZMA_MEM_ERROR;
198 
199  next->code = &index_encode;
200  next->end = &index_encoder_end;
201  }
202 
203  index_encoder_reset(next->coder, i);
204 
205  return LZMA_OK;
206 }
207 
208 
210 lzma_index_encoder(lzma_stream *strm, const lzma_index *i)
211 {
213 
216 
217  return LZMA_OK;
218 }
219 
220 
221 extern LZMA_API(lzma_ret)
222 lzma_index_buffer_encode(const lzma_index *i,
223  uint8_t *out, size_t *out_pos, size_t out_size)
224 {
225  // Validate the arguments.
226  if (i == NULL || out == NULL || out_pos == NULL || *out_pos > out_size)
227  return LZMA_PROG_ERROR;
228 
229  // Don't try to encode if there's not enough output space.
230  if (out_size - *out_pos < lzma_index_size(i))
231  return LZMA_BUF_ERROR;
232 
233  // The Index encoder needs just one small data structure so we can
234  // allocate it on stack.
235  lzma_index_coder coder;
236  index_encoder_reset(&coder, i);
237 
238  // Do the actual encoding. This should never fail, but store
239  // the original *out_pos just in case.
240  const size_t out_start = *out_pos;
241  lzma_ret ret = index_encode(&coder, NULL, NULL, NULL, 0,
242  out, out_pos, out_size, LZMA_RUN);
243 
244  if (ret == LZMA_STREAM_END) {
245  ret = LZMA_OK;
246  } else {
247  // We should never get here, but just in case, restore the
248  // output position and set the error accordingly if something
249  // goes wrong and debugging isn't enabled.
250  assert(0);
251  *out_pos = out_start;
252  ret = LZMA_PROG_ERROR;
253  }
254 
255  return ret;
256 }
lzma_index ** i
Definition: index.h:629
@ LZMA_INDEX_ITER_BLOCK
Get the next Block.
Definition: index.h:249
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
Handling of Index.
#define NULL
Definition: cris-opc.c:27
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_stream strm
Definition: full_flush.c:20
uint32_t lzma_index_padding_size(const lzma_index *i)
Definition: index.c:593
LZMA_API(lzma_ret)
static lzma_ret index_encode(void *coder_ptr, const lzma_allocator *allocator lzma_attribute((__unused__)), const uint8_t *restrict in lzma_attribute((__unused__)), size_t *restrict in_pos lzma_attribute((__unused__)), size_t in_size lzma_attribute((__unused__)), uint8_t *restrict out, size_t *restrict out_pos, size_t out_size, lzma_action action lzma_attribute((__unused__)))
Definition: index_encoder.c:44
lzma_ret lzma_index_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, const lzma_index *i)
static void index_encoder_reset(lzma_index_coder *coder, const lzma_index *i)
static void index_encoder_end(void *coder, const lzma_allocator *allocator)
Encodes the Index field.
voidpf void uLong size
Definition: ioapi.h:138
#define restrict
#define lzma_attribute(attr)
Definition: lzma.h:259
assert(limit<=UINT32_MAX/2)
unsigned int uint32_t
Definition: sftypes.h:29
unsigned char uint8_t
Definition: sftypes.h:31
Custom functions for memory handling.
Definition: base.h:372
lzma_index_iter iter
Iterator for the Index being encoded.
Definition: index_encoder.c:33
lzma_index * index
Target Index.
Definition: index_decoder.c:33
enum lzma_index_coder::@649 sequence
size_t pos
Position in integers.
Definition: index_decoder.c:49
const lzma_index * index
Index being encoded.
Definition: index_encoder.c:30
uint32_t crc32
CRC32 of the List of Records field.
Definition: index_decoder.c:52
Iterator to get information about Blocks and Streams.
Definition: index.h:43
struct lzma_index_iter::@636 block
lzma_vli unpadded_size
Unpadded size of this Block.
Definition: index.h:188
lzma_vli uncompressed_size
Uncompressed size of this Stream.
Definition: index.h:99
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
int pos
Definition: main.c:11
#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
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_STREAM_END
End of stream was reached.
Definition: base.h:63
@ LZMA_BUF_ERROR
No progress is possible.
Definition: base.h:191
@ 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
unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len)
Definition: crc32.c:1063