Use of RNum.calc in rax2 to honor error code ##tools

This commit is contained in:
pancake 2022-07-23 16:23:51 +02:00 committed by GitHub
parent e74aaf1127
commit 6ee9367a1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 174 additions and 178 deletions

View File

@ -440,7 +440,7 @@ static int cmd_seek(void *data, const char *input) {
case ' ': // "s "
{
ut64 addr = r_num_math (core->num, r_str_trim_head_ro (input));
if (core->num->nc.errors) {
if (core->num->nc.errors) { // TODO expose an api for this char *r_num_failed();
if (r_cons_singleton ()->context->is_interactive) {
eprintf ("Cannot seek to unknown address '%s'\n", core->num->nc.calc_buf);
}

View File

@ -39,7 +39,7 @@ typedef struct r_num_calc_t {
char string_value[R_NUMCALC_STRSZ];
int errors;
char oc;
const char *calc_err;
const char *calc_err; // rename to errstr
int calc_i;
const char *calc_buf;
int calc_len;

View File

@ -471,9 +471,9 @@ static int rasm_disasm(RAsmState *as, ut64 addr, const char *buf, int len, int b
}
ut8 bbuf[8] = {0};
int blen = is_binary (buf);
if (blen) {
char *nstr = r_str_newf ("0b%s", buf);
if (nstr[strlen (nstr)-1] == 'b') {
if (blen > 0) {
char *nstr = r_str_newf ("%s%s", r_str_startswith (buf, "0b")? "": "0b", buf);
if (nstr[strlen (nstr) - 1] == 'b') {
nstr[strlen (nstr)-1] = 0;
}
ut64 n = r_num_get (NULL, nstr);

View File

@ -1,23 +1,26 @@
/* radare - LGPL - Copyright 2007-2022 - pancake */
#define R_LOG_ORIGIN "rax2"
#include <r_main.h>
#include <r_util.h>
#include <r_util/r_print.h>
// don't use fixed sized buffers
// XXX don't use fixed sized buffers
#define STDIN_BUFFER_SIZE 354096
static int rax(RNum *num, char *str, int len, int last, ut64 *flags, int *fm);
static bool rax(RNum *num, char *str, int len, int last, ut64 *flags, int *fm);
static int use_stdin(RNum *num, ut64 *flags, int *fm) {
r_return_val_if_fail (num && flags, -1);
if (!flags) {
return 0;
}
char *buf = calloc (1, STDIN_BUFFER_SIZE + 1);
int l;
if (!buf) {
return 0;
}
if (!(*flags & (1<<14))) {
int l;
if (!(*flags & (1 << 14))) {
for (l = 0; l >= 0 && l < STDIN_BUFFER_SIZE; l++) {
// make sure we don't read beyond boundaries
int n = read (0, buf + l, STDIN_BUFFER_SIZE - l);
@ -40,15 +43,24 @@ static int use_stdin(RNum *num, ut64 *flags, int *fm) {
} else {
l = 1;
}
int rc = 0;
if (l > 0) {
rax (num, buf, l, 0, flags, fm);
if (!rax (num, buf, l, 0, flags, fm)) {
rc = 1;
}
}
free (buf);
return 0;
return rc;
}
static int format_output(RNum *num, char mode, const char *s, int force_mode, ut64 flags) {
ut64 n = r_num_math (num, s);
static bool format_output(RNum *num, char mode, const char *s, int force_mode, ut64 flags) {
const char *errstr = NULL;
ut64 n = r_num_calc (num, s, &errstr);
if (errstr) {
R_LOG_ERROR (errstr);
// eprintf ("%s\n", num->nc.calc_err);
return false;
}
char strbits[65];
if (force_mode) {
mode = force_mode;
@ -71,8 +83,11 @@ static int format_output(RNum *num, char mode, const char *s, int force_mode, ut
int n2 = (int) n;
float *f = (float *) &n2;
printf ("%ff\n", *f);
} break;
case 'f': printf ("%.01lf\n", num->fvalue); break;
}
break;
case 'f':
printf ("%.01lf\n", num->fvalue);
break;
case 'l':
R_STATIC_ASSERT (sizeof (float) == 4);
float f = (float) num->fvalue;
@ -97,8 +112,8 @@ static int format_output(RNum *num, char mode, const char *s, int force_mode, ut
}
break;
default:
eprintf ("Unknown output mode %d\n", mode);
break;
R_LOG_ERROR ("Unknown output mode %d", mode);
return false;
}
return true;
}
@ -163,7 +178,8 @@ static int help(void) {
return true;
}
static int rax(RNum *num, char *str, int len, int last, ut64 *_flags, int *fm) {
static bool rax(RNum *num, char *str, int len, int last, ut64 *_flags, int *fm) {
const char *errstr = NULL;
ut64 flags = *_flags;
const char *nl = "";
ut8 *buf;
@ -257,7 +273,7 @@ dotherax:
int n = ((strlen (str)) >> 1) + 1;
buf = malloc (n);
if (buf) {
memset (buf, '\0', n);
memset (buf, 0, n);
n = r_hex_str2bin (str, (ut8 *) buf);
if (n > 0) {
fwrite (buf, n, 1, stdout);
@ -265,7 +281,7 @@ dotherax:
#if __EMSCRIPTEN__
puts ("");
#else
if (nl && *nl) {
if (R_STR_ISNOTEMPTY (nl)) {
puts ("");
}
#endif
@ -306,8 +322,13 @@ dotherax:
ut32 *m = (ut32 *) buf;
memset (buf, '\0', n);
n = r_hex_str2bin (str, (ut8 *) buf);
if (n < 1 || !memcmp (str, "0x", 2)) {
ut64 q = r_num_math (num, str);
if (n < 1 || r_str_startswith (str, "0x")) {
ut64 q = r_num_calc (num, str, &errstr);
if (errstr) {
R_LOG_ERROR (errstr);
free (buf);
return false;
}
s = r_print_randomart ((ut8 *) &q, sizeof (q), q);
printf ("%s\n", s);
free (s);
@ -319,7 +340,11 @@ dotherax:
free (m);
return true;
} else if (flags & (1 << 9)) { // -n
ut64 n = r_num_math (num, str);
ut64 n = r_num_calc (num, str, &errstr);
if (errstr) {
R_LOG_ERROR (errstr);
return false;
}
if (n >> 32) {
/* is 64 bit value */
if (flags & 1) {
@ -365,7 +390,11 @@ dotherax:
}
return true;
} else if (flags & (1 << 16)) { // -w
ut64 n = r_num_math (num, str);
ut64 n = r_num_calc (num, str, &errstr);
if (errstr) {
R_LOG_ERROR (errstr);
return false;
}
if (n >> 31) {
// is >32bit
n = (st64) (st32) n;
@ -377,7 +406,11 @@ dotherax:
printf ("%" PFMT64d "\n", n);
return true;
} else if (flags & (1 << 15)) { // -N
ut64 n = r_num_math (num, str);
ut64 n = r_num_calc (num, str, &errstr);
if (errstr) {
R_LOG_ERROR (errstr);
return false;
}
if (n >> 32) {
/* is 64 bit value */
if (flags & 1) {
@ -406,8 +439,12 @@ dotherax:
}
return true;
} else if (flags & (1 << 10)) { // -u
char buf[8];
r_num_units (buf, sizeof (buf), r_num_math (NULL, str));
char buf[8] = {0};
r_num_units (buf, sizeof (buf), r_num_calc (NULL, str, &errstr));
if (errstr) {
R_LOG_ERROR (errstr);
return false;
}
printf ("%s\n", buf);
return true;
} else if (flags & (1 << 11)) { // -t
@ -417,10 +454,18 @@ dotherax:
if (r_list_length (split) >= 2 && strlen (r_list_head (split)->n->data) > 2) {
gmt = (const char*) r_list_head (split)->n->data + 2;
}
ut32 n = r_num_math (num, ts);
ut32 n = r_num_calc (num, ts, &errstr);
if (errstr) {
R_LOG_ERROR (errstr);
return false;
}
RPrint *p = r_print_new ();
if (gmt) {
p->datezone = r_num_math (num, gmt);
p->datezone = r_num_calc (num, gmt, &errstr);
if (errstr) {
R_LOG_ERROR (errstr);
return false;
}
}
r_print_date_unix (p, (const ut8 *) &n, sizeof (ut32));
r_print_free (p);
@ -456,7 +501,7 @@ dotherax:
fflush (stdout);
free (res);
} else {
eprintf ("Invalid input.\n");
R_LOG_ERROR ("Invalid input");
}
free (s);
}
@ -467,10 +512,14 @@ dotherax:
ut32 n32, s, a;
double d;
float f;
ut64 n = r_num_math (num, str);
if (num->dbz) {
eprintf ("RNum ERROR: Division by Zero\n");
const char *errstr = NULL;
ut64 n = r_num_calc (num, str, &errstr);
if (errstr) {
R_LOG_ERROR (errstr);
return false;
}
if (num->dbz) { // XXX should be done in errstr already
R_LOG_ERROR ("division by zero");
return false;
}
n32 = (ut32) (n & UT32_MAX);
@ -531,24 +580,30 @@ dotherax:
r_print_hex_from_bin (NULL, str);
return true;
} else if (flags & (1 << 21)) { // -i
printf ("unsigned char buf[] = {");
RStrBuf *sb = r_strbuf_new ("unsigned char buf[] = {");
/* reasonable amount of bytes per line */
const int byte_per_col = 12;
for (i = 0; i < len-1; i++) {
/* wrapping every N bytes */
if (i % byte_per_col == 0) {
printf ("\n ");
r_strbuf_append (sb, "\n ");
}
printf ("0x%02x, ", (ut8) str[i]);
r_strbuf_appendf (sb, "0x%02x, ", (ut8) str[i]);
}
/* some care for the last element */
if (i % byte_per_col == 0) {
printf("\n ");
r_strbuf_append (sb, "\n ");
}
printf ("0x%02x\n", (ut8) str[len - 1]);
printf ("};\n");
printf ("unsigned int buf_len = %d;\n", len);
return true;
r_strbuf_appendf (sb, "0x%02x\n", (ut8) str[len - 1]);
r_strbuf_append (sb, "};\n");
r_strbuf_appendf (sb, "unsigned int buf_len = %d;\n", len);
char *s = r_strbuf_drain (sb);
if (s) {
printf ("%s\n", s);
free (s);
return true;
}
return false;
} else if (flags & (1 << 22)) { // -o
// check -r
// flags & (1 << 18)
@ -561,10 +616,15 @@ dotherax:
modified_str = r_str_new (str);
}
ut64 n = r_num_math (num, modified_str);
const char *errstr = NULL;
ut64 n = r_num_calc (num, modified_str, &errstr);
free (modified_str);
if (errstr) {
R_LOG_ERROR ("Division by Zero");
return false;
}
if (num->dbz) {
eprintf ("RNum ERROR: Division by Zero\n");
R_LOG_ERROR ("Division by Zero");
return false;
}
@ -573,7 +633,7 @@ dotherax:
printf ("%s", asnum);
free (asnum);
} else {
eprintf ("No String Possible\n");
R_LOG_ERROR ("Not a string");
return false;
}
return true;
@ -584,14 +644,19 @@ dotherax:
ut32 ip32 = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
printf ("0x%08x\n", ip32);
} else {
ut32 ip32 = (ut32)r_num_math (NULL, str);
const char *errstr = NULL;
ut32 ip32 = (ut32)r_num_calc (NULL, str, &errstr);
if (errstr) {
R_LOG_ERROR (errstr);
return false;
}
ut8 ip[4] = { ip32 & 0xff, (ip32 >> 8) & 0xff, (ip32 >> 16) & 0xff, ip32 >> 24 };
printf ("%d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
}
return true;
}
if (str[0] == '0' && (tolower ((unsigned char)str[1]) == 'x')) {
if (str[0] == '0' && (tolower ((ut8)str[1]) == 'x')) {
out_mode = (flags & 32)? '0': 'I';
} else if (r_str_startswith (str, "b")) {
out_mode = 'B';
@ -624,17 +689,20 @@ dotherax:
}
while ((p = strchr (str, ' '))) {
*p = 0;
format_output (num, out_mode, str, *fm, flags);
if (!format_output (num, out_mode, str, *fm, flags)) {
return false;
}
str = p + 1;
}
if (*str) {
format_output (num, out_mode, str, *fm, flags);
return format_output (num, out_mode, str, *fm, flags);
}
return true;
}
R_API int r_main_rax2(int argc, const char **argv) {
int i, fm = 0;
int rc = 0;
if (argc < 2) {
help_usage ();
// use_stdin (num, NULL, &fm);
@ -643,11 +711,15 @@ R_API int r_main_rax2(int argc, const char **argv) {
ut64 flags = 0;
for (i = 1; i < argc; i++) {
char *argv_i = strdup (argv[i]);
r_str_unescape (argv_i);
rax (num, argv_i, 0, i == argc - 1, &flags, &fm);
free (argv_i);
if (argv_i) {
r_str_unescape (argv_i);
if (!rax (num, argv_i, 0, i == argc - 1, &flags, &fm)) {
rc = 1;
}
free (argv_i);
}
}
r_num_free (num);
}
return 0;
return rc;
}

View File

@ -346,14 +346,21 @@ static RNumCalcToken get_token(RNum *num, RNumCalc *nc) {
}
stringValueAppend(ch);
if (ch == '[') {
while (cin_get (num, nc, &ch) && ch!=']') {
while (cin_get (num, nc, &ch) && ch != ']') {
if (i > R_NUMCALC_STRSZ - 1) {
error (num, nc, "string too long");
return 0;
}
stringValueAppend(ch);
}
if (ch != ']') {
error (num, nc, "cannot find closing ]");
return 0;
}
stringValueAppend(ch);
} else if (ch == ']') {
error (num, nc, "cannot find opening [");
return 0;
} else {
while (cin_get (num, nc, &ch) && isvalidchar ((unsigned char)ch)) {
if (i >= R_NUMCALC_STRSZ) {

View File

@ -1,13 +1,12 @@
/* radare - LGPL - Copyright 2007-2022 - pancake */
#if __WINDOWS__
#include <stdlib.h>
#endif
#define R_LOG_ORIGIN "util.num"
#include <errno.h>
#include <math.h> /* for ceill */
#include <stdlib.h>
#include <r_util.h>
#define R_NUM_USE_CALC 1
static ut64 r_num_tailff(RNum *num, const char *hex);
@ -76,13 +75,12 @@ R_API void r_num_minmax_swap_i(int *a, int *b) {
R_API RNum *r_num_new(RNumCallback cb, RNumCallback2 cb2, void *ptr) {
RNum *num = R_NEW0 (RNum);
if (!num) {
return NULL;
if (num) {
num->value = 0LL;
num->callback = cb;
num->cb_from_value = cb2;
num->userptr = ptr;
}
num->value = 0LL;
num->callback = cb;
num->cb_from_value = cb2;
num->userptr = ptr;
return num;
}
@ -149,31 +147,40 @@ R_API const char *r_num_get_name(RNum *num, ut64 n) {
static void error(RNum *num, const char *err_str) {
if (num) {
num->nc.errors++;
#if 0
num->nc.calc_err = err_str;
#endif
if (err_str) {
num->nc.errors++;
num->nc.calc_err = err_str;
} else {
num->nc.errors = 0;
num->nc.calc_err = NULL;
}
}
}
static ut64 r_num_from_binary(const char *str) {
static ut64 r_num_from_binary(RNum *num, const char *str) {
int i, j;
ut64 ret = 0;
for (j = 0, i = strlen (str) - 1; i > 0; i--, j++) {
if (str[i] == '_') {
for (j = 0, i = strlen (str) - 1; i >= 0; i--, j++) {
switch (str[i]) {
case '_':
j--;
} else if (str[i] == '1') {
ret |= (ut64) (1ULL << j);
} else if (str[i] != '0') {
break;
case '1':
ret |= (ut64) (1ULL << j);
break;
case '0':
break;
default:
error (num, "binary numbers must contain only 0 and 1");
return 0;
}
}
sscanf (str, "0x%"PFMT64x, &ret);
// sscanf (str, "0x%"PFMT64x, &ret);
return ret;
}
R_API ut64 r_num_from_ternary(const char *inp) {
if (!inp) {
if (R_STR_ISEMPTY (inp)) {
return 0LL;
}
const char *p;
@ -202,15 +209,10 @@ R_API ut64 r_num_get(RNum *num, const char *str) {
ut32 s, a;
if (num && !num->nc.under_calc) {
num->nc.errors = 0;
error (num, NULL);
}
if (!str) {
return 0;
}
for (; *str == ' '; ) {
str++;
}
if (!*str) {
str = r_str_trim_head_ro (str);
if (R_STR_ISEMPTY (str)) {
return 0;
}
if (!strncmp (str, "1u", 2)) { // '1' is captured by op :(
@ -255,7 +257,7 @@ R_API ut64 r_num_get(RNum *num, const char *str) {
}
}
if (str[0] == '0' && str[1] == 'b') { // XXX this is wrong and causes bugs
ret = r_num_from_binary (str + 2);
ret = r_num_from_binary (num, str + 2);
} else if (str[0] == '\'') {
ret = str[1] & 0xff;
// ugly as hell
@ -421,7 +423,7 @@ R_API ut64 r_num_get(RNum *num, const char *str) {
if (errno == ERANGE) {
error (num, "number won't fit into 64 bits");
}
if (!IS_DIGIT (*str) || (*endptr && *endptr != lch)) {
if (!IS_DIGIT (*str) && (*endptr && *endptr != lch)) {
error (num, "unknown symbol");
}
break;
@ -433,110 +435,23 @@ R_API ut64 r_num_get(RNum *num, const char *str) {
return ret;
}
#if !R_NUM_USE_CALC
static ut64 r_num_op(RNum *num, char op, ut64 a, ut64 b) {
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/':
if (!b && num) num->dbz = 1;
return b ? a / b : 0;
case '&': return a & b;
case '|': return a | b;
case '^': return a ^ b;
}
return b;
}
R_API static ut64 r_num_math_internal(RNum *num, char *s) {
ut64 ret = 0LL;
char *p = s;
int i, nop, op = 0;
for (i=0; s[i]; i++) {
if (r_num_is_op (s[i])) {
nop = s[i]; s[i] = '\0';
ret = r_num_op (num, op, ret, r_num_get (num, p));
op = s[i] = nop; p = s + i + 1;
break;
}
}
return r_num_op (op, ret, r_num_get (num, p));
}
#endif /* !R_NUM_USE_CALC */
R_API ut64 r_num_math(RNum *num, const char *str) {
#if R_NUM_USE_CALC
ut64 ret;
const char *err = NULL;
if (!str || !*str) {
if (R_STR_ISEMPTY (str)) {
return 0LL;
}
// if (!str || !*str) return 0LL;
if (num) {
num->dbz = 0;
}
ret = r_num_calc (num, str, &err);
ret = r_num_calc (num, str, &err); // TODO: rename r_num_calc to r_num_math_err()
if (err) {
eprintf ("r_num_calc error: (%s) in (%s)\n", err, str);
R_LOG_DEBUG ("(%s) in (%s)", err, str);
}
if (num) {
num->value = ret;
}
return ret;
#else
ut64 ret = 0LL;
char op = '+';
int len;
char *p, *s, *os;
char *group;
if (!str) return 0LL;
len = strlen (str) + 1;
os = malloc (len + 1);
s = os;
memcpy (s, str, len);
for (; *s == ' '; s++);
p = s;
do {
group = strchr (p, '(');
if (group) {
group[0] = '\0';
ret = r_num_op (op, ret, r_num_math_internal (num, p));
for (; p<group; p += 1) {
if (r_num_is_op (*p)) {
op = *p;
break;
}
}
group[0] = '(';
p = group + 1;
if (r_str_delta (p, '(', ')') < 0) {
char *p2 = strchr (p, '(');
if (p2) {
*p2 = '\0';
ret = r_num_op (op, ret, r_num_math_internal (num, p));
ret = r_num_op (op, ret, r_num_math (num, p2 + 1));
p = p2 + 1;
continue;
}
eprintf ("WTF!\n");
} else {
ret = r_num_op (op, ret, r_num_math_internal (num, p));
}
} else {
ret = r_num_op (op, ret, r_num_math_internal (num, p));
}
} while (0);
if (num) {
num->value = ret;
}
free (os);
return ret;
#endif
}
R_API int r_num_is_float(RNum *num, const char *str) {
@ -799,7 +714,7 @@ R_API ut64 r_num_tail(RNum *num, ut64 addr, const char *hex) {
if (isxdigit ((ut8)hex[0])) {
n = r_num_math (num, p);
} else {
eprintf ("Invalid argument\n");
R_LOG_ERROR ("Invalid argument");
free (p);
return addr;
}
@ -823,7 +738,7 @@ static ut64 r_num_tailff(RNum *num, const char *hex) {
if (isxdigit ((ut8)hex[0])) {
n = r_num_get (num, p);
} else {
eprintf ("Invalid argument\n");
R_LOG_ERROR ("Invalid argument");
free (p);
return UT64_MAX;
}

View File

@ -4348,6 +4348,8 @@ EOF
EXPECT_ERR=<<EOF
DEBUG: Dynamic tag 16 not handled
Cannot determine entrypoint, using 0x00000d28.
DEBUG: (cannot find opening [) in (48])
DEBUG: (cannot find opening [) in (56])
EOF
RUN