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