1 /* radare - LGPL - Copyright 2007-2020 - pancake */
2
3 #include "r_types.h"
4 #include "r_util.h"
5 #include <stdio.h>
6 #include <ctype.h>
7
8 /* int c; ret = hex_to_byte(&c, 'c'); */
r_hex_to_byte(ut8 * val,ut8 c)9 R_API bool r_hex_to_byte(ut8 *val, ut8 c) {
10 if (IS_DIGIT (c)) {
11 *val = (ut8)(*val) * 16 + (c - '0');
12 } else if (c >= 'A' && c <= 'F') {
13 *val = (ut8)(*val) * 16 + (c - 'A' + 10);
14 } else if (c >= 'a' && c <= 'f') {
15 *val = (ut8)(*val) * 16 + (c - 'a' + 10);
16 } else {
17 return true;
18 }
19 return false;
20 }
21
r_hex_from_py_str(char * out,const char * code)22 R_API char *r_hex_from_py_str(char *out, const char *code) {
23 if (!strncmp (code, "'''", 3)) {
24 const char *s = code + 2;
25 return r_hex_from_c_str (out, &s);
26 }
27 return r_hex_from_c_str (out, &code);
28 }
29
skip_comment_py(const char * code)30 static const char *skip_comment_py(const char *code) {
31 if (*code != '#') {
32 return code;
33 }
34 char *end = strchr (code, '\n');
35 if (end) {
36 code = end;
37 }
38 return code + 1;
39 }
40
r_hex_from_py_array(char * out,const char * code)41 R_API char *r_hex_from_py_array(char *out, const char *code) {
42 const char abc[] = "0123456789abcdef";
43 if (*code != '[' || !strchr (code, ']')) {
44 return NULL;
45 }
46 code++;
47 for (; *code; code++) {
48 char *comma = strchr (code, ',');
49 if (!comma) {
50 comma = strchr (code, ']');
51 }
52 if (!comma) {
53 break;
54 }
55 char * _word = r_str_ndup (code, comma - code);
56 const char *word = _word;
57 while (*word == ' ' || *word == '\t' || *word == '\n') {
58 word++;
59 word = skip_comment_py (word);
60 }
61 if (IS_DIGIT (*word)) {
62 ut8 n = (ut8)r_num_math (NULL, word);
63 *out++ = abc[(n >> 4) & 0xf];
64 *out++ = abc[n & 0xf];
65 }
66 free (_word);
67 code = comma;
68 if (*code == ']') {
69 break;
70 }
71 }
72 return out;
73 }
74
r_hex_from_py(const char * code)75 R_API char* r_hex_from_py(const char *code) {
76 if (!code) {
77 return NULL;
78 }
79 char * const ret = malloc (strlen (code) * 3);
80 if (!ret) {
81 return NULL;
82 }
83 *ret = '\0';
84 char *out = ret;
85 const char *tmp_code = strchr (code, '=');
86 if (tmp_code) {
87 code = tmp_code;
88 }
89 for (; *code && *code != '[' && *code != '\''
90 && *code != '"'; code++) {
91 code = skip_comment_py (code);
92 }
93 if (*code == '[') {
94 out = r_hex_from_py_array (out, code);
95 } else if (*code == '"' || *code == '\'') {
96 out = r_hex_from_py_str (out, code);
97 }
98 if (!out) {
99 free (ret);
100 return NULL;
101 }
102 *out = '\0';
103 return ret;
104 }
105
r_hex_from_c_str(char * out,const char ** code)106 R_API char *r_hex_from_c_str(char *out, const char **code) {
107 const char abc[] = "0123456789abcdefABCDEF";
108 const char *iter = *code;
109 if (*iter != '\'' && *iter != '"') {
110 return NULL;
111 }
112 const char end_char = *iter;
113 iter++;
114 for (; *iter && *iter != end_char; iter++) {
115 if (*iter == '\\') {
116 iter++;
117 switch (iter[0]) {
118 case 'e': *out++='1';*out++='b';break;
119 case 'r': *out++='0';*out++='d';break;
120 case 'n': *out++='0';*out++='a';break;
121 case 'x': {
122 ut8 c1 = iter[1];
123 ut8 c2 = iter[2];
124 iter += 2;
125 if (c1 == '\0' || c2 == '\0') {
126 return NULL;
127 } else if (strchr (abc, c1) && strchr (abc, c2)) {
128 *out++ = tolower (c1);
129 *out++ = tolower (c2);
130 } else {
131 return NULL;
132 }
133 break;
134 }
135 default:
136 if (iter[0] == end_char) {
137 *out++ = abc[*iter >> 4];
138 *out++ = abc[*iter & 0xf];
139 }
140 return NULL;
141 }
142 } else {
143 *out++ = abc[*iter >> 4];
144 *out++ = abc[*iter & 0xf];
145 }
146 }
147 *code = iter;
148 return out;
149 }
150
skip_comment_c(const char * code)151 const char *skip_comment_c(const char *code) {
152 if (!strncmp (code, "/*", 2)) {
153 char *end = strstr (code, "*/");
154 if (end) {
155 code = end + 2;
156 } else {
157 eprintf ("Missing closing comment\n");
158 }
159 } else if (!strncmp (code, "//", 2)) {
160 char *end = strchr (code, '\n');
161 if (end) {
162 code = end + 2;
163 }
164 }
165 return code;
166 }
167
r_hex_from_c_array(char * out,const char * code)168 R_API char *r_hex_from_c_array(char *out, const char *code) {
169 const char abc[] = "0123456789abcdef";
170 if (*code != '{' || !strchr(code, '}')) {
171 return NULL;
172 }
173 code++;
174 for (; *code; code++) {
175 const char *comma = strchr (code, ',');
176 if (!comma) {
177 comma = strchr (code, '}');
178 }
179 char * _word = r_str_ndup (code, comma - code);
180 const char *word = _word;
181 word = skip_comment_c (word);
182 while (*word == ' ' || *word == '\t' || *word == '\n') {
183 word++;
184 word = skip_comment_c (word);
185 }
186 if (IS_DIGIT (*word)) {
187 ut8 n = (ut8)r_num_math (NULL, word);
188 *out++ = abc[(n >> 4) & 0xf];
189 *out++ = abc[n & 0xf];
190 }
191 free (_word);
192 code = comma;
193 if (*code == '}') {
194 break;
195 }
196 }
197 return out;
198 }
199
200 /* convert:
201 * char *foo = "\x41\x23\x42\x1b";
202 * into:
203 * 4123421b
204 */
r_hex_from_c(const char * code)205 R_API char *r_hex_from_c(const char *code) {
206 if (!code) {
207 return NULL;
208 }
209 char * const ret = malloc (strlen (code) * 3);
210 if (!ret) {
211 return NULL;
212 }
213 *ret = '\0';
214 char *out = ret;
215 const char *tmp_code = strchr (code, '=');
216 if (tmp_code) {
217 code = tmp_code;
218 }
219 for (; *code != '\0' && *code != '{' && *code != '"'; code++) {
220 code = skip_comment_c (code);
221 }
222 if (*code == '{') {
223 out = r_hex_from_c_array (out, code);
224 } else if (*code == '"') {
225 const char *s1, *s2;
226 s1 = code;
227 do {
228 code = s1;
229 out = r_hex_from_c_str (out, &code);
230 if (!out) {
231 break;
232 }
233 s1 = strchr (code + 1, '"');
234 s2 = strchr (code + 1, ';');
235 } while (s1 && s2 && (s1 <= s2));
236 }
237 if (!out) {
238 free (ret);
239 return NULL;
240 }
241 *out = '\0';
242 return ret;
243 }
244
245
r_hex_from_js(const char * code)246 R_API char *r_hex_from_js(const char *code) {
247 char * s1 = strchr (code, '\'');
248 char * s2 = strchr (code, '"');
249
250 /* there are no strings in the input */
251 if (!(s1 || s2)) {
252 return NULL;
253 }
254
255 char * start, * end;
256 if (s1 < s2) {
257 start = s1;
258 end = strchr (start + 1, '\'');
259 } else {
260 start = s2;
261 end = strchr (start + 1, '"');
262 }
263
264 /* the string isn't properly terminated */
265 if (!end) {
266 return NULL;
267 }
268
269 char * str = r_str_ndup (start + 1, end - start - 1);
270
271 /* assuming base64 input, output will always be shorter */
272 ut8 *b64d = malloc (end - start);
273 if (!b64d) {
274 free (str);
275 return NULL;
276 }
277
278 r_base64_decode (b64d, str, end - start - 1);
279 if (!b64d) {
280 free (str);
281 free (b64d);
282 return NULL;
283 }
284
285 // TODO: use r_str_bin2hex
286 int i, len = strlen ((const char *)b64d);
287 char * out = malloc (len * 2 + 1);
288 if (!out) {
289 free (str);
290 free (b64d);
291 return NULL;
292 }
293 for (i = 0; i < len; i++) {
294 sprintf (&out[i * 2], "%02x", b64d[i]);
295 }
296 out[len * 2] = '\0';
297
298 free (str);
299 free (b64d);
300 return out;
301 }
302
303 /* convert
304 * "\x41\x23\x42\x1b"
305 * "\x41\x23\x42\x1b"
306 * into
307 * 4123421b4123421b
308 */
r_hex_no_code(const char * code)309 R_API char *r_hex_no_code(const char *code) {
310 if (!code) {
311 return NULL;
312 }
313 char * const ret = calloc (1, strlen (code) * 3);
314 if (!ret) {
315 return NULL;
316 }
317 *ret = '\0';
318 char *out = ret;
319 out = r_hex_from_c_str (out, &code);
320 code = strchr (code + 1, '"');
321 if (!out) {
322 free (ret);
323 return NULL;
324 }
325 *out = '\0';
326 while (out && code) {
327 *out = '\0';
328 out = r_hex_from_c_str (out, &code);
329 code = strchr (code + 1, '"');
330 }
331 return ret;
332 }
333
r_hex_from_code(const char * code)334 R_API char *r_hex_from_code(const char *code) {
335 if (!strchr (code, '=')) {
336 return r_hex_no_code (code);
337 }
338 /* C language */
339 if (strstr (code, "char") || strstr (code, "int")) {
340 return r_hex_from_c (code);
341 }
342 /* JavaScript */
343 if (strstr (code, "var")) {
344 return r_hex_from_js (code);
345 }
346 /* Python */
347 return r_hex_from_py (code);
348 }
349
350 /* int byte = hexpair2bin("A0"); */
351 // (0A) => 10 || -1 (on error)
r_hex_pair2bin(const char * arg)352 R_API int r_hex_pair2bin(const char *arg) {
353 ut8 *ptr, c = 0, d = 0;
354 ut32 j = 0;
355
356 for (ptr = (ut8*)arg; ;ptr = ptr + 1) {
357 if (!*ptr || *ptr==' ' || j==2) {
358 break;
359 }
360 d = c;
361 if (*ptr != '.' && r_hex_to_byte (&c, *ptr)) {
362 eprintf ("Invalid hexa string at char '%c' (%s).\n",
363 *ptr, arg);
364 return -1;
365 }
366 c |= d;
367 if (j++ == 0) {
368 c <<= 4;
369 }
370 }
371 return (int)c;
372 }
373
r_hex_bin2str(const ut8 * in,int len,char * out)374 R_API int r_hex_bin2str(const ut8 *in, int len, char *out) {
375 int i, idx;
376 char tmp[8];
377 if (len < 0) {
378 return 0;
379 }
380 for (idx = i = 0; i < len; i++, idx += 2) {
381 snprintf (tmp, sizeof (tmp), "%02x", in[i]);
382 memcpy (out + idx, tmp, 2);
383 }
384 out[idx] = 0;
385 return len;
386 }
387
r_hex_bin2strdup(const ut8 * in,int len)388 R_API char *r_hex_bin2strdup(const ut8 *in, int len) {
389 int i, idx;
390 char tmp[5], *out;
391
392 if ((len + 1) * 2 < len) {
393 return NULL;
394 }
395 out = malloc ((len + 1) * 2);
396 if (!out) {
397 return NULL;
398 }
399 for (i = idx = 0; i < len; i++, idx += 2) {
400 snprintf (tmp, sizeof (tmp), "%02x", in[i]);
401 memcpy (out+idx, tmp, 2);
402 }
403 out[idx] = 0;
404 return out;
405 }
406
r_hex_str2bin(const char * in,ut8 * out)407 R_API int r_hex_str2bin(const char *in, ut8 *out) {
408 long nibbles = 0;
409
410 while (in && *in) {
411 ut8 tmp;
412 /* skip hex prefix */
413 if (*in == '0' && in[1] == 'x') {
414 in += 2;
415 }
416 /* read hex digits */
417 while (!r_hex_to_byte (out ? &out[nibbles/2] : &tmp, *in)) {
418 nibbles++;
419 in++;
420 }
421 if (*in == '\0') {
422 break;
423 }
424 /* comments */
425 if (*in == '#' || (*in == '/' && in[1] == '/')) {
426 if ((in = strchr (in, '\n'))) {
427 in++;
428 }
429 continue;
430 } else if (*in == '/' && in[1] == '*') {
431 if ((in = strstr (in, "*/"))) {
432 in += 2;
433 }
434 continue;
435 } else if (!IS_WHITESPACE (*in) && *in != '\n') {
436 /* this is not a valid string */
437 return 0;
438 }
439 /* ignore character */
440 in++;
441 }
442
443 if (nibbles % 2) {
444 if (out) {
445 r_hex_to_byte (&out[nibbles / 2], '0');
446 }
447 return -(nibbles+1) / 2;
448 }
449
450 return nibbles / 2;
451 }
452
r_hex_str2binmask(const char * in,ut8 * out,ut8 * mask)453 R_API int r_hex_str2binmask(const char *in, ut8 *out, ut8 *mask) {
454 ut8 *ptr;
455 int len, ilen = strlen (in)+1;
456 int has_nibble = 0;
457 memcpy (out, in, ilen);
458 for (ptr = out; *ptr; ptr++) {
459 if (*ptr == '.') {
460 *ptr = '0';
461 }
462 }
463 len = r_hex_str2bin ((char*)out, out);
464 if (len<0) { has_nibble = 1; len = -(len+1); }
465 if (len != -1) {
466 memcpy (mask, in, ilen);
467 if (has_nibble) {
468 memcpy (mask + ilen, "f0", 3);
469 }
470 for (ptr = mask; *ptr; ptr++) {
471 if (IS_HEXCHAR (*ptr)) {
472 *ptr = 'f';
473 } else if (*ptr == '.') {
474 *ptr = '0';
475 }
476 }
477 len = r_hex_str2bin ((char*)mask, mask);
478 if (len < 0) {
479 len++;
480 }
481 }
482 return len;
483 }
484
r_hex_bin_truncate(ut64 in,int n)485 R_API st64 r_hex_bin_truncate(ut64 in, int n) {
486 switch (n) {
487 case 1:
488 if ((in & UT8_GT0)) {
489 return UT64_8U | in;
490 }
491 return in&UT8_MAX;
492 case 2:
493 if ((in & UT16_GT0)) {
494 return UT64_16U | in;
495 }
496 return in&UT16_MAX;
497 case 4:
498 if ((in & UT32_GT0)) {
499 return UT64_32U | in;
500 }
501 return in&UT32_MAX;
502 case 8:
503 return in&UT64_MAX;
504 }
505 return in;
506 }
507
508 // Check if str contains only hexadecimal characters and return length of bytes
r_hex_str_is_valid(const char * str)509 R_API int r_hex_str_is_valid(const char* str) {
510 int i;
511 int len = 0;
512 if (!strncmp (str, "0x", 2)) {
513 str += 2;
514 }
515 for (i = 0; str[i] != '\0'; i++) {
516 if (IS_HEXCHAR (str[i])) {
517 len++;
518 }
519 if (IS_HEXCHAR (str[i]) || IS_WHITESPACE (str[i])) {
520 continue;
521 }
522 return -1; //if we're here, then str isn't valid
523 }
524 return len;
525 }
526