From 467ca68d48a314a50e432f3efdb9a6bb0c1ef26a Mon Sep 17 00:00:00 2001 From: pancake Date: Mon, 1 Nov 2021 22:38:53 +0100 Subject: [PATCH] Save and check the reg arena size when peekpoking (Fix tests_64923) ##crash --- libr/core/agraph.c | 20 +++++++++++--------- libr/core/cmd_anal.c | 5 +++-- libr/core/cmd_print.c | 15 ++++++++------- libr/core/disasm.c | 8 ++++---- libr/include/r_anal.h | 2 ++ libr/include/r_reg.h | 4 ++-- libr/reg/arena.c | 12 ++++++++++-- 7 files changed, 40 insertions(+), 26 deletions(-) diff --git a/libr/core/agraph.c b/libr/core/agraph.c index cff7e8e5ff..74c60b3771 100644 --- a/libr/core/agraph.c +++ b/libr/core/agraph.c @@ -2136,18 +2136,18 @@ static char *get_body(RCore *core, ut64 addr, int size, int opts) { return body; } -static char *get_bb_body(RCore *core, RAnalBlock *b, int opts, RAnalFunction *fcn, bool emu, ut64 saved_gp, ut8 *saved_arena) { +static char *get_bb_body(RCore *core, RAnalBlock *b, int opts, RAnalFunction *fcn, bool emu, ut64 saved_gp, ut8 *saved_arena, int saved_arena_size) { if (emu) { core->anal->gp = saved_gp; if (b->parent_reg_arena) { - r_reg_arena_poke (core->anal->reg, b->parent_reg_arena); + r_reg_arena_poke (core->anal->reg, b->parent_reg_arena, b->parent_reg_arena_size); R_FREE (b->parent_reg_arena); ut64 gp = r_reg_getv (core->anal->reg, "gp"); if (gp) { core->anal->gp = gp; } } else { - r_reg_arena_poke (core->anal->reg, saved_arena); + r_reg_arena_poke (core->anal->reg, saved_arena, saved_arena_size); } } if (b->parent_stackptr != INT_MAX) { @@ -2193,13 +2193,14 @@ static void get_bbupdate(RAGraph *g, RCore *core, RAnalFunction *fcn) { bool emu = r_config_get_i (core->config, "asm.emu"); ut64 saved_gp = core->anal->gp; ut8 *saved_arena = NULL; + int saved_arena_size = 0; int saved_stackptr = core->anal->stackptr; char *shortcut = 0; int shortcuts = 0; core->keep_asmqjmps = false; if (emu) { - saved_arena = r_reg_arena_peek (core->anal->reg); + saved_arena = r_reg_arena_peek (core->anal->reg, &saved_arena_size); } if (!fcn) { R_FREE (saved_arena); @@ -2212,7 +2213,7 @@ static void get_bbupdate(RAGraph *g, RCore *core, RAnalFunction *fcn) { if (bb->addr == UT64_MAX) { continue; } - char *body = get_bb_body (core, bb, mode2opts (g), fcn, emu, saved_gp, saved_arena); + char *body = get_bb_body (core, bb, mode2opts (g), fcn, emu, saved_gp, saved_arena, saved_arena_size); char *title = get_title (bb->addr); if (shortcuts) { @@ -2240,7 +2241,7 @@ static void get_bbupdate(RAGraph *g, RCore *core, RAnalFunction *fcn) { if (emu) { core->anal->gp = saved_gp; if (saved_arena) { - r_reg_arena_poke (core->anal->reg, saved_arena); + r_reg_arena_poke (core->anal->reg, saved_arena, saved_arena_size); R_FREE (saved_arena); } } @@ -2327,6 +2328,7 @@ static int get_bbnodes(RAGraph *g, RCore *core, RAnalFunction *fcn) { bool few = r_config_get_i (core->config, "graph.few"); int ret = false; ut64 saved_gp = core->anal->gp; + int saved_arena_size = 0; ut8 *saved_arena = NULL; int saved_stackptr = core->anal->stackptr; core->keep_asmqjmps = false; @@ -2335,7 +2337,7 @@ static int get_bbnodes(RAGraph *g, RCore *core, RAnalFunction *fcn) { return false; } if (emu) { - saved_arena = r_reg_arena_peek (core->anal->reg); + saved_arena = r_reg_arena_peek (core->anal->reg, &saved_arena_size); } r_list_sort (fcn->bbs, (RListComparator) bbcmp); RAnalBlock *curbb = NULL; @@ -2359,7 +2361,7 @@ static int get_bbnodes(RAGraph *g, RCore *core, RAnalFunction *fcn) { if (few && !isbbfew (curbb, bb)) { continue; } - char *body = get_bb_body (core, bb, mode2opts (g), fcn, emu, saved_gp, saved_arena); + char *body = get_bb_body (core, bb, mode2opts (g), fcn, emu, saved_gp, saved_arena, saved_arena_size); char *title = get_title (bb->addr); char *color = (bb->color.r || bb->color.g || bb->color.b)? r_cons_rgb_str (NULL, -1, &bb->color): NULL; RANode *node = r_agraph_add_node (g, title, body, color); @@ -2410,7 +2412,7 @@ cleanup: if (emu) { core->anal->gp = saved_gp; if (saved_arena) { - r_reg_arena_poke (core->anal->reg, saved_arena); + r_reg_arena_poke (core->anal->reg, saved_arena, saved_arena_size); R_FREE (saved_arena); } } diff --git a/libr/core/cmd_anal.c b/libr/core/cmd_anal.c index c7a796a13d..9e298a9641 100644 --- a/libr/core/cmd_anal.c +++ b/libr/core/cmd_anal.c @@ -1049,14 +1049,15 @@ static bool cmd_anal_aaft(RCore *core) { r_reg_arena_push (core->anal->reg); r_reg_arena_zero (core->anal->reg); r_core_cmd0 (core, "aei;aeim"); - ut8 *saved_arena = r_reg_arena_peek (core->anal->reg); + int saved_arena_size = 0; + ut8 *saved_arena = r_reg_arena_peek (core->anal->reg, &saved_arena_size); // Iterating Reverse so that we get function in top-bottom call order r_list_foreach_prev (core->anal->fcns, it, fcn) { int ret = r_core_seek (core, fcn->addr, true); if (!ret) { continue; } - r_reg_arena_poke (core->anal->reg, saved_arena); + r_reg_arena_poke (core->anal->reg, saved_arena, saved_arena_size); r_anal_esil_set_pc (core->anal->esil, fcn->addr); r_core_anal_type_match (core, fcn); if (r_cons_is_breaked ()) { diff --git a/libr/core/cmd_print.c b/libr/core/cmd_print.c index 148a0813a4..f79f700c93 100644 --- a/libr/core/cmd_print.c +++ b/libr/core/cmd_print.c @@ -4178,8 +4178,8 @@ static void __printPattern(RCore *core, const char *_input) { free (input); } -static void pr_bb(RCore *core, RAnalFunction *fcn, RAnalBlock *b, bool emu, ut64 saved_gp, ut8 *saved_arena, char p_type, bool fromHere) { - bool show_flags = r_config_get_i (core->config, "asm.flags"); +static void pr_bb(RCore *core, RAnalFunction *fcn, RAnalBlock *b, bool emu, ut64 saved_gp, ut8 *saved_arena, int saved_arena_size, char p_type, bool fromHere) { + bool show_flags = r_config_get_b (core->config, "asm.flags"); const char *orig_bb_middle = r_config_get (core->config, "asm.bbmiddle"); core->anal->gp = saved_gp; if (fromHere) { @@ -4192,14 +4192,14 @@ static void pr_bb(RCore *core, RAnalFunction *fcn, RAnalBlock *b, bool emu, ut64 if (emu) { if (b->parent_reg_arena) { ut64 gp; - r_reg_arena_poke (core->anal->reg, b->parent_reg_arena); + r_reg_arena_poke (core->anal->reg, b->parent_reg_arena, b->parent_reg_arena_size); R_FREE (b->parent_reg_arena); gp = r_reg_getv (core->anal->reg, "gp"); if (gp) { core->anal->gp = gp; } } else { - r_reg_arena_poke (core->anal->reg, saved_arena); + r_reg_arena_poke (core->anal->reg, saved_arena, saved_arena_size); } } if (b->parent_stackptr != INT_MAX) { @@ -4435,20 +4435,21 @@ static void func_walk_blocks(RCore *core, RAnalFunction *f, char input, char typ bool asm_lines = r_config_get_i (core->config, "asm.lines.jmp"); bool emu = r_config_get_i (core->config, "asm.emu"); ut64 saved_gp = 0; + int saved_arena_size = 0; ut8 *saved_arena = NULL; int saved_stackptr = core->anal->stackptr; if (emu) { saved_gp = core->anal->gp; - saved_arena = r_reg_arena_peek (core->anal->reg); + saved_arena = r_reg_arena_peek (core->anal->reg, &saved_arena_size); } r_config_set_i (core->config, "asm.lines.jmp", 0); r_list_foreach (f->bbs, iter, b) { - pr_bb (core, f, b, emu, saved_gp, saved_arena, type_print, fromHere); + pr_bb (core, f, b, emu, saved_gp, saved_arena, saved_arena_size, type_print, fromHere); } if (emu) { core->anal->gp = saved_gp; if (saved_arena) { - r_reg_arena_poke (core->anal->reg, saved_arena); + r_reg_arena_poke (core->anal->reg, saved_arena, saved_arena_size); R_FREE (saved_arena); } } diff --git a/libr/core/disasm.c b/libr/core/disasm.c index 021481a30e..ebd93e1006 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -579,11 +579,11 @@ static void ds_print_esil_anal_fini(RDisasmState *ds) { RCore *core = ds->core; if (ds->show_emu && ds->esil_regstate) { RCore* core = ds->core; - core->anal->last_disasm_reg = r_reg_arena_peek (core->anal->reg); + core->anal->last_disasm_reg = r_reg_arena_peek (core->anal->reg, &core->anal->last_disasm_reg_size); const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC); RRegSet *regset = r_reg_regset_get (ds->core->anal->reg, R_REG_TYPE_GPR); - if (ds->esil_regstate_size == regset->arena->size) { - r_reg_arena_poke (core->anal->reg, ds->esil_regstate); + if (ds->esil_regstate_size == regset->arena->size) { + r_reg_arena_poke (core->anal->reg, ds->esil_regstate, ds->esil_regstate_size); } r_reg_setv (core->anal->reg, pc, ds->esil_old_pc); R_FREE (ds->esil_regstate); @@ -4697,7 +4697,7 @@ static void ds_print_esil_anal_init(RDisasmState *ds) { if (core->anal->gp) { r_reg_setv (core->anal->reg, "gp", core->anal->gp); } - ds->esil_regstate = r_reg_arena_peek (core->anal->reg); + ds->esil_regstate = r_reg_arena_peek (core->anal->reg, &ds->esil_regstate_size); RRegSet *regset = r_reg_regset_get (core->anal->reg, R_REG_TYPE_GPR); if (ds->esil_regstate && regset) { ds->esil_regstate_size = regset->arena->size; diff --git a/libr/include/r_anal.h b/libr/include/r_anal.h index 0e0b9d783a..af950aa49b 100644 --- a/libr/include/r_anal.h +++ b/libr/include/r_anal.h @@ -624,6 +624,7 @@ typedef struct r_anal_t { HtPP *ht_name_fun; // name => function RReg *reg; ut8 *last_disasm_reg; + int last_disasm_reg_size; RSyscall *syscall; int diff_ops; double diff_thbb; @@ -927,6 +928,7 @@ typedef struct r_anal_bb_t { ut16 *op_pos; // offsets of instructions in this block, count is ninstr - 1 (first is always 0) ut8 *op_bytes; ut8 *parent_reg_arena; + int parent_reg_arena_size; int op_pos_size; // size of the op_pos array int ninstr; int stackptr; diff --git a/libr/include/r_reg.h b/libr/include/r_reg.h index fcdf226f2e..0974a9818a 100644 --- a/libr/include/r_reg.h +++ b/libr/include/r_reg.h @@ -226,8 +226,8 @@ R_API int r_reg_arena_push(RReg *reg); R_API void r_reg_arena_pop(RReg *reg); R_API void r_reg_arena_zero(RReg *reg); -R_API ut8 *r_reg_arena_peek(RReg *reg); -R_API void r_reg_arena_poke(RReg *reg, const ut8 *buf); +R_API ut8 *r_reg_arena_peek(RReg *reg, int *len); +R_API void r_reg_arena_poke(RReg *reg, const ut8 *buf, int len); R_API ut8 *r_reg_arena_dup(RReg *reg, const ut8 *source); R_API const char *r_reg_cond_to_string(int n); R_API int r_reg_cond_from_string(const char *str); diff --git a/libr/reg/arena.c b/libr/reg/arena.c index 453f1fb821..d9891d826e 100644 --- a/libr/reg/arena.c +++ b/libr/reg/arena.c @@ -263,7 +263,7 @@ R_API void r_reg_arena_zero(RReg *reg) { } } -R_API ut8 *r_reg_arena_peek(RReg *reg) { +R_API ut8 *r_reg_arena_peek(RReg *reg, int *size) { RRegSet *regset = r_reg_regset_get (reg, R_REG_TYPE_GPR); if (!reg || !regset || !regset->arena || (regset->arena->size < 1)) { return NULL; @@ -273,14 +273,22 @@ R_API ut8 *r_reg_arena_peek(RReg *reg) { return NULL; } memcpy (ret, regset->arena->bytes, regset->arena->size); + if (size) { + *size = regset->arena->size; + } return ret; } -R_API void r_reg_arena_poke(RReg *reg, const ut8 *ret) { +R_API void r_reg_arena_poke(RReg *reg, const ut8 *ret, int len) { RRegSet *regset = r_reg_regset_get (reg, R_REG_TYPE_GPR); if (!ret || !regset || !regset->arena || !regset->arena->bytes) { return; } + if (len > 0 && len != regset->arena->size) { + eprintf ("Invalid size of the arena bytes to poke (%d vs %d).\n", + len, regset->arena->size); + return; + } memcpy (regset->arena->bytes, ret, regset->arena->size); }