Fix max asm len in pickle ##arch

This commit is contained in:
Dennis Goodlett 2023-05-28 00:32:53 -04:00 committed by pancake
parent 22a085cca8
commit 7f2c2d75ce

View File

@ -171,10 +171,11 @@ static inline bool valid_offset(RArch *a, ut64 addr) {
return true;
}
static inline bool handle_int(RAnalOp *op, const char *name, int sz, const ut8 *buf, int buflen) {
static inline bool handle_int(RAnalOp *op, const char *name, int sz) {
int buflen = op->size - 1;
if (sz <= buflen && sz <= sizeof (op->val)) {
op->size += sz;
op->val = r_mem_get_num (buf, sz);
op->size = sz + 1;
op->val = r_mem_get_num (op->bytes + 1, sz);
free (op->mnemonic);
op->mnemonic = r_str_newf ("%s 0x%" PFMT64x, name, op->val);
return true;
@ -182,18 +183,19 @@ static inline bool handle_int(RAnalOp *op, const char *name, int sz, const ut8 *
return false;
}
static inline int handle_long(RArch *a, RAnalOp *op, const char *name, int sz, const ut8 *buf, int buflen) {
static inline int handle_long(RArch *a, RAnalOp *op, int sz) {
r_return_val_if_fail (sz == 1 || sz == 4, -1);
op->sign = true;
// process how long the numer is is
if (sz > buflen) {
if (sz >= op->size) {
return -1;
}
const ut8 *buf = op->bytes + 1;
ut64 longlen = r_mem_get_num (buf, sz);
buf += sz;
buflen -= sz;
op->size += sz + longlen;
int buflen = op->size - sz + 1;
op->size = sz + longlen + 1;
if (longlen <= sizeof (op->val) && longlen <= buflen) {
op->val = 0;
@ -221,12 +223,13 @@ static inline int handle_long(RArch *a, RAnalOp *op, const char *name, int sz, c
return op->size;
}
static inline int handle_float(RAnalOp *op, const char *name, int sz, const ut8 *buf, int buflen) {
static inline int handle_float(RAnalOp *op, const char *name, int sz) {
int buflen = op->size - 1;
if (sz <= buflen && sz <= sizeof (op->val)) {
op->family = R_ANAL_OP_FAMILY_FPU;
op->size += sz;
op->size = sz + 1;
double d;
memcpy (&d, buf, sz);
memcpy (&d, op->bytes + 1, sz);
r_mem_swap ((ut8 *)&d, sizeof (d));
op->ptr = op->addr + op->nopcode;
op->ptrsize = sz;
@ -275,17 +278,30 @@ static inline char *get_two_lines(const ut8 *buf, int len) {
return NULL;
}
static inline bool handle_n_lines(RAnalOp *op, const char *name, int n, const ut8 *buf, int buflen) {
r_return_val_if_fail (buflen >= 0 && name && n < 3 && n > 0, -1);
static inline void max_oplen_set(RArchSession *s, RAnalOp *op) {
// update max opsise
if (op->size > MAXSTRLEN && s->data) {
int *x = (int *)s->data;
if (*x < op->size) {
*x = op->size;
}
}
}
static inline bool handle_n_lines(RArchSession *s, RAnalOp *op, const char *name, int n) {
r_return_val_if_fail (op->size >= 2 && name && n < 3 && n > 0, -1);
// TODO: use an alternative func for INT, FLOAT, LONG ops that gets the
// value from arg str
const ut8 *buf = op->bytes + 1;
int buflen = op->size - 1;
char *str = (n == 2)? get_two_lines (buf, buflen): get_line (buf, buflen);
if (str) {
op->ptr = op->addr + op->nopcode;
op->ptrsize = strlen (str) + 1;
op->size += op->ptrsize;
op->size = op->ptrsize + 1;
op->mnemonic = r_str_newf ("%s \"%s\"", name, str);
free (str);
max_oplen_set (s, op);
return true;
}
op->type = R_ANAL_OP_TYPE_ILL;
@ -293,7 +309,9 @@ static inline bool handle_n_lines(RAnalOp *op, const char *name, int n, const ut
return false;
}
static inline int handle_opstring(RAnalOp *op, const ut8 *buf, int buflen) {
static inline int handle_opstring(RArchSession *s, RAnalOp *op) {
const ut8 *buf = op->bytes + 1;
int buflen = op->size - 1;
if (buf[0] != '\'') {
op->type = R_ANAL_OP_TYPE_ILL;
return -1;
@ -310,6 +328,7 @@ static inline int handle_opstring(RAnalOp *op, const ut8 *buf, int buflen) {
op->ptrsize = len - 1; // remove last ' from len
op->size = 2 + op->ptrsize + 2; // (S') + str + ('\n)
free (str);
max_oplen_set (s, op);
return op->size;
}
free (str);
@ -333,15 +352,18 @@ static inline void set_mnemonic_str(RAnalOp *op, const char *n, const ut8 *buf,
}
}
static bool cnt_str(RArch *a, RAnalOp *op, const char *name, int sz, const ut8 *buf, int buflen) {
static bool cnt_str(RArchSession *s, RAnalOp *op, const char *name, int sz) {
const ut8 *buf = op->bytes + 1;
int buflen = op->size - 1;
if (sz <= buflen && sz <= sizeof (op->val)) {
op->ptrsize = r_mem_get_num (buf, sz);
op->size = op->nopcode + sz + op->ptrsize;
op->ptr = op->addr + sz + op->nopcode;
if (valid_offset (a, op->addr + op->size - 1)) {
if (valid_offset (s->arch, op->addr + op->size - 1)) {
buflen -= sz;
buf += sz;
set_mnemonic_str (op, name, buf, R_MIN (buflen, MAXSTRLEN));
max_oplen_set (s, op);
return true;
} else {
op->size = 1;
@ -356,20 +378,13 @@ static bool pickle_decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
if (op->size < 1 || !op->bytes) {
return false;
}
const ut8 *buf = op->bytes;
RArch *a = s->arch; // s->arch;
int len = op->size;
// all opcodes are 1 byte, some have arbitrarily large strings as args
op->nopcode = 1;
op->size = 1;
op->family = R_ANAL_OP_FAMILY_CPU;
op->type = R_ANAL_OP_TYPE_MOV;
char opcode = *buf;
buf++;
len--;
const char *opstr = NULL;
switch (opcode) {
switch ((char)*op->bytes) {
case OP_MARK:
opstr = "mark";
break;
@ -386,24 +401,24 @@ static bool pickle_decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
opstr = "dup";
break;
case OP_FLOAT:
return handle_n_lines (op, "float", 1, buf, len);
return handle_n_lines (s, op, "float", 1);
case OP_INT:
return handle_n_lines (op, "int", 1, buf, len);
return handle_n_lines (s, op, "int", 1);
case OP_BININT:
op->sign = true;
return handle_int (op, "binint", 4, buf, len);
return handle_int (op, "binint", 4);
case OP_BININT1:
return handle_int (op, "binint1", 1, buf, len);
return handle_int (op, "binint1", 1);
case OP_LONG:
return handle_n_lines (op, "long", 1, buf, len);
return handle_n_lines (s, op, "long", 1);
case OP_BININT2:
return handle_int (op, "binint2", 2, buf, len);
return handle_int (op, "binint2", 2);
case OP_NONE:
opstr = "none";
break;
case OP_PERSID:
// TODO: validate
return handle_n_lines (op, "persid", 1, buf, len);
return handle_n_lines (s, op, "persid", 1);
case OP_BINPERSID:
opstr = "binpersid";
break;
@ -411,15 +426,15 @@ static bool pickle_decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
opstr = "reduce";
break;
case OP_STRING:
return handle_opstring (op, buf, len);
return handle_opstring (s, op);
case OP_BINSTRING:
return cnt_str (a, op, "binstring", 4, buf, len);
return cnt_str (s, op, "binstring", 4);
case OP_SHORT_BINSTRING:
return cnt_str (a, op, "short_binstring", 1, buf, len);
return cnt_str (s, op, "short_binstring", 1);
case OP_UNICODE:
return handle_n_lines (op, "unicode", 1, buf, len);
return handle_n_lines (s, op, "unicode", 1);
case OP_BINUNICODE:
return cnt_str (a, op, "binunicode", 4, buf, len);
return cnt_str (s, op, "binunicode", 4);
case OP_APPEND:
opstr = "append";
break;
@ -427,7 +442,7 @@ static bool pickle_decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
opstr = "build";
break;
case OP_GLOBAL:
return handle_n_lines (op, "global", 2, buf, len);
return handle_n_lines (s, op, "global", 2);
case OP_DICT:
opstr = "dict";
break;
@ -438,14 +453,14 @@ static bool pickle_decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
opstr = "appends";
break;
case OP_GET:
return handle_n_lines (op, "get", 1, buf, len);
return handle_n_lines (s, op, "get", 1);
case OP_BINGET:
op->sign = true; // I think
return handle_int (op, "binget", 1, buf, len);
return handle_int (op, "binget", 1);
case OP_INST:
return handle_n_lines (op, "inst", 2, buf, len);
return handle_n_lines (s, op, "inst", 2);
case OP_LONG_BINGET:
return handle_int (op, "long_binget", 4, buf, len);
return handle_int (op, "long_binget", 4);
case OP_LIST:
opstr = "list";
break;
@ -456,11 +471,11 @@ static bool pickle_decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
opstr = "obj";
break;
case OP_PUT:
return handle_n_lines (op, "put", 1, buf, len);
return handle_n_lines (s, op, "put", 1);
case OP_BINPUT:
return handle_int (op, "binput", 1, buf, len);
return handle_int (op, "binput", 1);
case OP_LONG_BINPUT:
return handle_int (op, "long_binput", 4, buf, len);
return handle_int (op, "long_binput", 4);
case OP_SETITEM:
opstr = "setitem";
break;
@ -474,19 +489,19 @@ static bool pickle_decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
opstr = "setitems";
break;
case OP_BINFLOAT:
return handle_float (op, "binfloat", 8, buf, len);
return handle_float (op, "binfloat", 8);
case OP_PROTO:
return handle_int (op, "proto", 1, buf, len);
return handle_int (op, "proto", 1);
case OP_NEWOBJ:
opstr = "newobj";
break;
case OP_EXT1:
// I don't *think* it's signed
return handle_int (op, "ext1", 1, buf, len);
return handle_int (op, "ext1", 1);
case OP_EXT2:
return handle_int (op, "ext2", 2, buf, len);
return handle_int (op, "ext2", 2);
case OP_EXT4:
return handle_int (op, "ext4", 4, buf, len);
return handle_int (op, "ext4", 4);
case OP_TUPLE1:
opstr = "tuple1";
break;
@ -503,19 +518,19 @@ static bool pickle_decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
opstr = "newfalse";
break;
case OP_LONG1:
return handle_long (a, op, "long1", 1, buf, len);
return handle_long (s->arch, op, 1);
case OP_LONG4:
return handle_long (a, op, "long1", 4, buf, len);
return handle_long (s->arch, op, 4);
case OP_BINBYTES:
return cnt_str (a, op, "binbytes", 4, buf, len);
return cnt_str (s, op, "binbytes", 4);
case OP_SHORT_BINBYTES:
return cnt_str (a, op, "short_binbytes", 1, buf, len);
return cnt_str (s, op, "short_binbytes", 1);
case OP_SHORT_BINUNICODE:
return cnt_str (a, op, "short_binunicode", 1, buf, len);
return cnt_str (s, op, "short_binunicode", 1);
case OP_BINUNICODE8:
return cnt_str (a, op, "binunicode8", 8, buf, len);
return cnt_str (s, op, "binunicode8", 8);
case OP_BINBYTES8:
return cnt_str (a, op, "binbytes8", 8, buf, len);
return cnt_str (s, op, "binbytes8", 8);
case OP_EMPTY_SET:
opstr = "empty_set";
break;
@ -535,9 +550,9 @@ static bool pickle_decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
opstr = "memoize";
break;
case OP_FRAME:
return handle_int (op, "frame", 8, buf, len);
return handle_int (op, "frame", 8);
case OP_BYTEARRAY8:
return cnt_str (a, op, "bytearray8", 8, buf, len);
return cnt_str (s, op, "bytearray8", 8);
case OP_NEXT_BUFFER:
opstr = "next_buffer";
break;
@ -554,6 +569,7 @@ static bool pickle_decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
op->type = R_ANAL_OP_TYPE_ILL;
return false;
}
return true;
}
@ -906,7 +922,10 @@ static int pickle_info(RArchSession *s, ut32 q) {
return 0;
case R_ANAL_ARCHINFO_MAX_OP_SIZE:
// some ops accept newline terminated strings of arbitrary len...
return MAXSTRLEN + 1;
if (s->data) {
return *(int *)s->data;
}
return MAXSTRLEN;
case R_ANAL_ARCHINFO_INV_OP_SIZE:
return 1;
case R_ANAL_ARCHINFO_MIN_OP_SIZE:
@ -952,6 +971,23 @@ static char *pickle_mnemonics(RArchSession *s, int id, bool json) {
return NULL;
}
static bool pickle_init(RArchSession *s) {
r_return_val_if_fail (s, false);
s->data = R_NEW (int);
if (s->data) {
*((int *)s->data) = MAXSTRLEN;
return true;
}
return false;
}
static bool pickle_fini(RArchSession *s) {
r_return_val_if_fail (s, false);
free (s->data);
s->data = NULL;
return true;
}
RArchPlugin r_arch_plugin_pickle = {
.name = "pickle",
.desc = "Python Pickle Machine Disassembler",
@ -962,6 +998,8 @@ RArchPlugin r_arch_plugin_pickle = {
.encode = &pickle_encode,
.info = pickle_info,
.mnemonics = pickle_mnemonics,
.init = pickle_init,
.fini = pickle_fini,
};
#ifndef R2_PLUGIN_INCORE