/* radare - LGPL - Copyright 2007-2016 - pancake */ #include "r_types.h" #include "r_util.h" #include /* int c; ret = hex_to_byte(&c, 'c'); */ R_API int r_hex_to_byte(ut8 *val, ut8 c) { if (c >= '0' && c <= '9') { *val = (ut8)(*val) * 16 + (c - '0'); } else if (c >= 'A' && c <= 'F') { *val = (ut8)(*val) * 16 + (c - 'A' + 10); } else if (c >= 'a' && c <= 'f') { *val = (ut8)(*val) * 16 + (c - 'a' + 10); } else { return 1; } return 0; } /* convert: * char *foo = "\x41\x23\x42\x1b"; * into: * 4123421b */ R_API char *r_hex_from_c(const char *code) { const char abc[] = "0123456789abcdefABCDEF"; bool parse_on = false; int parse_mode = 0; char *out, *ret; int is_hexa = 0; if (code) { ret = malloc (strlen (code) * 3); } else { ret = malloc (3); } if (!ret) return NULL; *ret = 0; out = ret; if (code) { for (;*code; code++) { if (!strncmp (code, "/*", 2)) { /* skip comments */ char *end = strstr (code, "*/"); if (end) { code = end + 1; } else { eprintf ("Missing closing comment\n"); } continue; } if (!strncmp (code, "//", 2)) { char *end = strchr (code, '\n'); if (end) { code = end; } continue; } if (parse_on) { if (*code == '}' || *code == '"') { parse_on = false; // stop parsing after the first string statement break; } } else { if (*code == '{') { parse_mode = *code; for (code++;*code; code++) { if (IS_WHITESPACE (*code)) continue; if (IS_NUMBER (*code)) { parse_on = true; break; } else { parse_on = false; parse_mode = 0; break; } } } } if (parse_on && parse_mode == '{') { char *comma = strchr (code, ','); if (!comma) comma = strchr (code, '}'); if (comma) { char *word = r_str_ndup (code, comma - code); if (IS_NUMBER (*word)) { ut8 n = (ut8)r_num_math (NULL, word); *out++ = abc[(n >> 4) & 0xf]; *out++ = abc[n & 0xf]; } else { parse_on = false; } code = comma; free (word); } } else if (*code == '"') { if (code[1] == '\\') { parse_on = true; } else { parse_on = !parse_on; parse_mode = *code; } } else if (parse_on) { if (*code == '\\') { code++; switch (code[0]) { case 'e': *out++='1';*out++='b';break; case 'r': *out++='0';*out++='d';break; case 'n': *out++='0';*out++='a';break; case 'x': is_hexa ++; break; default: goto error; } } else { if (is_hexa) { if (strchr (abc, *code)) { *out++ = *code; if (++is_hexa == 3) is_hexa = 0; } else goto error; } else { *out++ = abc[*code >>4]; *out++ = abc[*code & 0xf]; } } } } } *out++ = 0; return ret; error: free (ret); return NULL; } /* int byte = hexpair2bin("A0"); */ // (0A) => 10 || -1 (on error) R_API int r_hex_pair2bin(const char *arg) { ut8 *ptr, c = 0, d = 0; ut32 j = 0; for (ptr = (ut8*)arg; ;ptr = ptr + 1) { if (!*ptr || *ptr==' ' || j==2) { break; } d = c; if (*ptr!='.' && r_hex_to_byte (&c, *ptr)) { eprintf ("Invalid hexa string at char '%c' (%s).\n", *ptr, arg); return -1; } c |= d; if (j++ == 0) { c <<= 4; } } return (int)c; } R_API int r_hex_bin2str(const ut8 *in, int len, char *out) { int i, idx; char tmp[5]; if (len < 0) return 0; for (idx = i = 0; i < len; i++, idx += 2) { snprintf (tmp, sizeof (tmp), "%02x", in[i]); memcpy (out+idx, tmp, 2); } out[idx] = 0; return len; } R_API char *r_hex_bin2strdup(const ut8 *in, int len) { int i, idx; char tmp[5], *out; if ((len + 1) * 2 < len) return NULL; out = malloc ((len + 1) * 2); if (!out) return NULL; for (i = idx = 0; i < len; i++, idx += 2) { snprintf (tmp, sizeof (tmp), "%02x", in[i]); memcpy (out+idx, tmp, 2); } out[idx] = 0; return out; } R_API int r_hex_str2bin(const char *in, ut8 *out) { long nibbles = 0; while (in && *in) { ut8 tmp; /* skip hex prefix */ if (*in == '0' && in[1] == 'x') { in += 2; } /* read hex digits */ while (!r_hex_to_byte (out ? &out[nibbles/2] : &tmp, *in)) { nibbles++; in++; } if (*in == '\0') { break; } /* comments */ if (*in == '#' || (*in == '/' && in[1] == '/')) { if ((in = strchr (in, '\n'))) in++; continue; } else if (*in == '/' && in[1] == '*') { if ((in = strstr (in, "*/"))) in += 2; continue; } else if (!IS_WHITESPACE (*in) && *in != '\n') { /* this is not a valid string */ return 0; } /* ignore character */ in++; } if (nibbles % 2) { if (out) r_hex_to_byte (&out[nibbles/2], '0'); return -(nibbles+1) / 2; } return nibbles / 2; } R_API int r_hex_str2binmask(const char *in, ut8 *out, ut8 *mask) { ut8 *ptr; int len, ilen = strlen (in)+1; int has_nibble = 0; memcpy (out, in, ilen); for (ptr=out; *ptr; ptr++) if (*ptr=='.') *ptr = '0'; len = r_hex_str2bin ((char*)out, out); if (len<0) { has_nibble = 1; len = -(len+1); } if (len != -1) { memcpy (mask, in, ilen); if (has_nibble) memcpy (mask+ilen, "f0", 3); for (ptr=mask; *ptr; ptr++) *ptr = (*ptr=='.')?'0':'f'; len = r_hex_str2bin ((char*)mask, mask); if (len<0) len++; } return len; } R_API st64 r_hex_bin_truncate (ut64 in, int n) { switch (n) { case 1: if ((in&UT8_GT0)) return UT64_8U|in; return in&UT8_MAX; case 2: if ((in&UT16_GT0)) return UT64_16U|in; return in&UT16_MAX; case 4: if ((in&UT32_GT0)) return UT64_32U|in; return in&UT32_MAX; case 8: return in&UT64_MAX; } return in; } // Check if str contains only hexademical characters and return length of bytes R_API int r_hex_str_is_valid(const char* str) { int i; if (!strncmp (str, "0x", 2)) { str += 2; } for (i = 0; str[i] != '\0' && str[i] != ' '; i++) { if (ishexchar (str[i])) { continue; } return -1; //if we're here, then str isnt valid } return i; }