Rizin
unix-like reverse engineering framework and cli tools
uleb128.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2014-2015 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "rz_util/rz_str.h"
5 #include <rz_util.h>
6 
7 /* dex/dwarf uleb128 implementation */
8 
9 RZ_API const ut8 *rz_uleb128(const ut8 *data, int datalen, RZ_NULLABLE ut64 *v, const char **error) {
10  ut8 c;
11  ut64 s, sum = 0;
12  const ut8 *data_end;
13  bool malformed_uleb = true;
14  if (v) {
15  *v = 0LL;
16  }
17  if (datalen == ST32_MAX) {
18  // WARNING; possible overflow
19  datalen = 0xffff;
20  }
21  if (datalen < 0) {
22  return NULL;
23  }
24  data_end = data + datalen;
25  if (data && datalen > 0) {
26  if (*data) {
27  for (s = 0; data < data_end; s += 7) {
28  c = *(data++) & 0xff;
29  if (s > 63) {
30  if (error) {
31  *error = rz_str_newf("rz_uleb128: undefined behaviour in %d shift on ut32\n", (int)s);
32  }
33  break;
34  } else {
35  sum |= ((ut64)(c & 0x7f) << s);
36  }
37  if (!(c & 0x80)) {
38  malformed_uleb = false;
39  break;
40  }
41  }
42  if (malformed_uleb) {
43  if (error) {
44  *error = rz_str_newf("malformed uleb128\n");
45  }
46  }
47  } else {
48  data++;
49  }
50  }
51  if (v) {
52  *v = sum;
53  }
54  return data;
55 }
56 
57 RZ_API int rz_uleb128_len(const ut8 *data, int size) {
58  int i = 1;
59  ut8 c = *(data++);
60  while (c > 0x7f && i < size) {
61  c = *(data++);
62  i++;
63  }
64  return i;
65 }
66 
67 /* data is the char array containing the uleb number
68  * datalen will point (if not NULL) to the length of the uleb number
69  * v (if not NULL) will point to the data's value (if fitting the size of an ut64)
70  */
71 RZ_API const ut8 *rz_uleb128_decode(const ut8 *data, int *datalen, ut64 *v) {
72  ut8 c = 0xff;
73  ut64 s = 0, sum = 0, l = 0;
74  do {
75  c = *(data++) & 0xff;
76  sum |= ((ut64)(c & 0x7f) << s);
77  s += 7;
78  l++;
79  } while (c & 0x80);
80  if (v) {
81  *v = sum;
82  }
83  if (datalen) {
84  *datalen = l;
85  }
86  return data;
87 }
88 
90  ut8 c = 0;
91  int l = 0;
92  ut8 *otarget = NULL, *target = NULL, *tmptarget = NULL;
93  ut64 source = s;
94  do {
95  l++;
96  if (!(tmptarget = realloc(otarget, l))) {
97  l = 0;
98  free(otarget);
99  otarget = NULL;
100  break;
101  }
102  otarget = tmptarget;
103  target = otarget + l - 1;
104  c = source & 0x7f;
105  source >>= 7;
106  if (source) {
107  c |= 0x80;
108  }
109  *(target) = c;
110  } while (source);
111  if (len) {
112  *len = l;
113  }
114  return otarget;
115 }
116 
117 RZ_API const ut8 *rz_leb128(const ut8 *data, int datalen, st64 *v) {
118  ut8 c = 0;
119  st64 s = 0, sum = 0;
120  const ut8 *data_end = data + datalen;
121  if (data && datalen > 0) {
122  if (!*data) {
123  data++;
124  goto beach;
125  }
126  while (data < data_end) {
127  c = *(data++) & 0x0ff;
128  sum |= ((st64)(c & 0x7f) << s);
129  s += 7;
130  if (!(c & 0x80)) {
131  break;
132  }
133  }
134  }
135  if ((s < (8 * sizeof(sum))) && (c & 0x40)) {
136  sum |= -((st64)1 << s);
137  }
138 beach:
139  if (v) {
140  *v = sum;
141  }
142  return data;
143 }
144 
145 RZ_API st64 rz_sleb128(const ut8 **data, const ut8 *end) {
146  const ut8 *p = *data;
147  st64 result = 0;
148  int offset = 0;
149  ut8 value;
150  bool cond;
151  do {
152  st64 chunk;
153  value = *p;
154  chunk = value & 0x7f;
155  result |= (chunk << offset);
156  offset += 7;
157  } while (cond = *p & 0x80 && p + 1 < end, p++, cond);
158 
159  if ((value & 0x40) != 0) {
160  result |= ~0ULL << offset;
161  }
162  *data = p;
163  return result;
164 }
165 
166 // API from https://github.com/WebAssembly/wabt/blob/master/src/binary-reader.cc
167 
168 #define BYTE_AT(type, i, shift) (((type)(p[i]) & 0x7f) << (shift))
169 
170 #define LEB128_1(type) (BYTE_AT(type, 0, 0))
171 #define LEB128_2(type) (BYTE_AT(type, 1, 7) | LEB128_1(type))
172 #define LEB128_3(type) (BYTE_AT(type, 2, 14) | LEB128_2(type))
173 #define LEB128_4(type) (BYTE_AT(type, 3, 21) | LEB128_3(type))
174 #define LEB128_5(type) (BYTE_AT(type, 4, 28) | LEB128_4(type))
175 #define LEB128_6(type) (BYTE_AT(type, 5, 35) | LEB128_5(type))
176 #define LEB128_7(type) (BYTE_AT(type, 6, 42) | LEB128_6(type))
177 #define LEB128_8(type) (BYTE_AT(type, 7, 49) | LEB128_7(type))
178 #define LEB128_9(type) (BYTE_AT(type, 8, 56) | LEB128_8(type))
179 #define LEB128_10(type) (BYTE_AT(type, 9, 63) | LEB128_9(type))
180 
181 #define SHIFT_AMOUNT(type, sign_bit) (sizeof(type) * 8 - 1 - (sign_bit))
182 #define SIGN_EXTEND(type, value, sign_bit) \
183  ((type)((value) << SHIFT_AMOUNT(type, sign_bit)) >> \
184  SHIFT_AMOUNT(type, sign_bit))
185 
186 RZ_API size_t read_u32_leb128(const ut8 *p, const ut8 *max, ut32 *out_value) {
187  if (p < max && !(p[0] & 0x80)) {
188  *out_value = LEB128_1(ut32);
189  return 1;
190  } else if (p + 1 < max && !(p[1] & 0x80)) {
191  *out_value = LEB128_2(ut32);
192  return 2;
193  } else if (p + 2 < max && !(p[2] & 0x80)) {
194  *out_value = LEB128_3(ut32);
195  return 3;
196  } else if (p + 3 < max && !(p[3] & 0x80)) {
197  *out_value = LEB128_4(ut32);
198  return 4;
199  } else if (p + 4 < max && !(p[4] & 0x80)) {
200  /* the top bits set represent values > 32 bits */
201  // if (p[4] & 0xf0) {}
202  *out_value = LEB128_5(ut32);
203  return 5;
204  } else {
205  /* past the end */
206  *out_value = 0;
207  return 0;
208  }
209 }
210 
211 RZ_API size_t read_i32_leb128(const ut8 *p, const ut8 *max, st32 *out_value) {
212  if (p < max && !(p[0] & 0x80)) {
213  ut32 result = LEB128_1(ut32);
214  *out_value = SIGN_EXTEND(ut32, result, 6);
215  return 1;
216  } else if (p + 1 < max && !(p[1] & 0x80)) {
217  ut32 result = LEB128_2(ut32);
218  *out_value = SIGN_EXTEND(ut32, result, 13);
219  return 2;
220  } else if (p + 2 < max && !(p[2] & 0x80)) {
221  ut32 result = LEB128_3(ut32);
222  *out_value = SIGN_EXTEND(ut32, result, 20);
223  return 3;
224  } else if (p + 3 < max && !(p[3] & 0x80)) {
225  ut32 result = LEB128_4(ut32);
226  *out_value = SIGN_EXTEND(ut32, result, 27);
227  return 4;
228  } else if (p + 4 < max && !(p[4] & 0x80)) {
229  /* the top bits should be a sign-extension of the sign bit */
230  bool sign_bit_set = (p[4] & 0x8);
231  int top_bits = p[4] & 0xf0;
232  if ((sign_bit_set && top_bits != 0x70) || (!sign_bit_set && top_bits != 0)) {
233  return 0;
234  }
235  ut32 result = LEB128_5(ut32);
236  *out_value = result;
237  return 5;
238  } else {
239  /* past the end */
240  return 0;
241  }
242 }
243 
244 RZ_API size_t read_u64_leb128(const ut8 *p, const ut8 *max, ut64 *out_value) {
245  if (p < max && !(p[0] & 0x80)) {
246  *out_value = LEB128_1(ut64);
247  return 1;
248  } else if (p + 1 < max && !(p[1] & 0x80)) {
249  *out_value = LEB128_2(ut64);
250  return 2;
251  } else if (p + 2 < max && !(p[2] & 0x80)) {
252  *out_value = LEB128_3(ut64);
253  return 3;
254  } else if (p + 3 < max && !(p[3] & 0x80)) {
255  *out_value = LEB128_4(ut64);
256  return 4;
257  } else if (p + 4 < max && !(p[4] & 0x80)) {
258  *out_value = LEB128_5(ut64);
259  return 5;
260  } else if (p + 5 < max && !(p[5] & 0x80)) {
261  *out_value = LEB128_6(ut64);
262  return 6;
263  } else if (p + 6 < max && !(p[6] & 0x80)) {
264  *out_value = LEB128_7(ut64);
265  return 7;
266  } else if (p + 7 < max && !(p[7] & 0x80)) {
267  *out_value = LEB128_8(ut64);
268  return 8;
269  } else if (p + 8 < max && !(p[8] & 0x80)) {
270  *out_value = LEB128_9(ut64);
271  return 9;
272  } else if (p + 9 < max && !(p[9] & 0x80)) {
273  *out_value = LEB128_10(ut64);
274  return 10;
275  } else {
276  /* past the end */
277  *out_value = 0;
278  return 0;
279  }
280 }
281 
282 RZ_API size_t read_i64_leb128(const ut8 *p, const ut8 *max, st64 *out_value) {
283  if (p < max && !(p[0] & 0x80)) {
284  ut64 result = LEB128_1(ut64);
285  *out_value = SIGN_EXTEND(ut64, result, 6);
286  return 1;
287  } else if (p + 1 < max && !(p[1] & 0x80)) {
288  ut64 result = LEB128_2(ut64);
289  *out_value = SIGN_EXTEND(ut64, result, 13);
290  return 2;
291  } else if (p + 2 < max && !(p[2] & 0x80)) {
292  ut64 result = LEB128_3(ut64);
293  *out_value = SIGN_EXTEND(ut64, result, 20);
294  return 3;
295  } else if (p + 3 < max && !(p[3] & 0x80)) {
296  ut64 result = LEB128_4(ut64);
297  *out_value = SIGN_EXTEND(ut64, result, 27);
298  return 4;
299  } else if (p + 4 < max && !(p[4] & 0x80)) {
300  ut64 result = LEB128_5(ut64);
301  *out_value = SIGN_EXTEND(ut64, result, 34);
302  return 5;
303  } else if (p + 5 < max && !(p[5] & 0x80)) {
304  ut64 result = LEB128_6(ut64);
305  *out_value = SIGN_EXTEND(ut64, result, 41);
306  return 6;
307  } else if (p + 6 < max && !(p[6] & 0x80)) {
308  ut64 result = LEB128_7(ut64);
309  *out_value = SIGN_EXTEND(ut64, result, 48);
310  return 7;
311  } else if (p + 7 < max && !(p[7] & 0x80)) {
312  ut64 result = LEB128_8(ut64);
313  *out_value = SIGN_EXTEND(ut64, result, 55);
314  return 8;
315  } else if (p + 8 < max && !(p[8] & 0x80)) {
316  ut64 result = LEB128_9(ut64);
317  *out_value = SIGN_EXTEND(ut64, result, 62);
318  return 9;
319  } else if (p + 9 < max && !(p[9] & 0x80)) {
320  /* the top bits should be a sign-extension of the sign bit */
321  bool sign_bit_set = (p[9] & 0x1);
322  int top_bits = p[9] & 0xfe;
323  if ((sign_bit_set && top_bits != 0x7e) || (!sign_bit_set && top_bits != 0)) {
324  return 0;
325  }
326  ut64 result = LEB128_10(ut64);
327  *out_value = result;
328  return 10;
329  } else {
330  /* past the end */
331  return 0;
332  }
333 }
334 
335 #undef BYTE_AT
336 #undef LEB128_1
337 #undef LEB128_2
338 #undef LEB128_3
339 #undef LEB128_4
340 #undef LEB128_5
341 #undef LEB128_6
342 #undef LEB128_7
343 #undef LEB128_8
344 #undef LEB128_9
345 #undef LEB128_10
346 #undef SHIFT_AMOUNT
347 #undef SIGN_EXTEND
348 
349 #if 0
350 main() {
351  ut32 n;
352  ut8 *buf = "\x10\x02\x90\x88";
353  rz_uleb128 (buf, &n);
354  printf ("n = %d\n", n);
355 }
356 #endif
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
uint32_t ut32
const char * v
Definition: dsignal.c:12
int max
Definition: enough.c:225
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
const char * source
Definition: lz4.h:699
int n
Definition: mipsasm.c:19
static RzSocket * s
Definition: rtr.c:28
int main(int argc, char **argv)
Definition: rz-bb.c:29
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_NULLABLE
Definition: rz_types.h:65
#define st64
Definition: rz_types_base.h:10
#define ST32_MAX
Definition: rz_types_base.h:97
#define st32
Definition: rz_types_base.h:12
#define c(i)
Definition: sha256.c:43
#define cond(bop, top, mask, flags)
Definition: malloc.c:21
RZ_API size_t read_u32_leb128(const ut8 *p, const ut8 *max, ut32 *out_value)
Definition: uleb128.c:186
RZ_API const ut8 * rz_uleb128(const ut8 *data, int datalen, RZ_NULLABLE ut64 *v, const char **error)
Definition: uleb128.c:9
RZ_API size_t read_i64_leb128(const ut8 *p, const ut8 *max, st64 *out_value)
Definition: uleb128.c:282
#define SIGN_EXTEND(type, value, sign_bit)
Definition: uleb128.c:182
#define LEB128_3(type)
Definition: uleb128.c:172
#define LEB128_10(type)
Definition: uleb128.c:179
RZ_API const ut8 * rz_leb128(const ut8 *data, int datalen, st64 *v)
Definition: uleb128.c:117
RZ_API const ut8 * rz_uleb128_decode(const ut8 *data, int *datalen, ut64 *v)
Definition: uleb128.c:71
RZ_API int rz_uleb128_len(const ut8 *data, int size)
Definition: uleb128.c:57
RZ_API st64 rz_sleb128(const ut8 **data, const ut8 *end)
Definition: uleb128.c:145
#define LEB128_7(type)
Definition: uleb128.c:176
#define LEB128_1(type)
Definition: uleb128.c:170
#define LEB128_5(type)
Definition: uleb128.c:174
RZ_API size_t read_i32_leb128(const ut8 *p, const ut8 *max, st32 *out_value)
Definition: uleb128.c:211
RZ_API ut8 * rz_uleb128_encode(const ut64 s, int *len)
Definition: uleb128.c:89
#define LEB128_4(type)
Definition: uleb128.c:173
#define LEB128_6(type)
Definition: uleb128.c:175
#define LEB128_2(type)
Definition: uleb128.c:171
#define LEB128_8(type)
Definition: uleb128.c:177
RZ_API size_t read_u64_leb128(const ut8 *p, const ut8 *max, ut64 *out_value)
Definition: uleb128.c:244
#define LEB128_9(type)
Definition: uleb128.c:178
void error(const char *msg)
Definition: untgz.c:593
ut64(WINAPI *w32_GetEnabledXStateFeatures)()