diff --git a/libr/cons/cons.c b/libr/cons/cons.c index 443a4806dfe4d..fed208a4b52aa 100644 --- a/libr/cons/cons.c +++ b/libr/cons/cons.c @@ -1602,11 +1602,32 @@ R_API RConsContext *r_cons_context_clone(RConsContext *ctx) { c->pal.rainbow = NULL; pal_clone (c); // rainbow_clone (c); - memset (&c->grep, 0, sizeof (c->grep)); + + c->grep = ctx->grep; + c->grep.str = ctx->grep.str? strdup (ctx->grep.str): NULL; + c->grep.json_path = ctx->grep.json_path? strdup (ctx->grep.json_path): NULL; c->grep.strings = r_list_newf ((RListFree)grep_word_free); - c->grep.line = -1; - c->grep.sort = -1; - c->grep.sort_invert = false; + if (ctx->grep.strings && c->grep.strings) { + RListIter *iter; + RConsGrepWord *gw; + r_list_foreach (ctx->grep.strings, iter, gw) { + RConsGrepWord *ngw = R_NEW0 (RConsGrepWord); + if (!ngw) { + continue; + } + *ngw = *gw; + ngw->str = NULL; + if (gw->str) { + ngw->str = strdup (gw->str); + if (!ngw->str) { + free (ngw); + continue; + } + } + r_list_append (c->grep.strings, ngw); + } + } + // Note: tokens array is copied via r_mem_dup return c; } diff --git a/libr/cons/dietline.c b/libr/cons/dietline.c index 735a34afaf34d..9ecab373c331d 100644 --- a/libr/cons/dietline.c +++ b/libr/cons/dietline.c @@ -646,7 +646,12 @@ R_API bool r_line_hist_add(RLine *line, const char *text) { return false; } if (!line->history.data) { - inithist (line); + if (!inithist (line)) { + return false; + } + } + if (!line->history.data || line->history.size <= 0) { + return false; } /* ignore dup */ if (line->history.top > 0) { diff --git a/libr/cons/line.c b/libr/cons/line.c index 396d6bd87fd47..f0243041c7be9 100644 --- a/libr/cons/line.c +++ b/libr/cons/line.c @@ -24,6 +24,7 @@ R_API RLine *r_line_new(RCons *cons) { line->clipboard = NULL; line->kill_ring = r_list_newf (free); line->kill_ring_ptr = -1; + line->hist_size = R_LINE_HISTSIZE; #if R2__WINDOWS__ line->vtmode = win_is_vtcompat (); #else diff --git a/libr/core/cmd.c b/libr/core/cmd.c index eb0067a53a55d..800692852ba79 100644 --- a/libr/core/cmd.c +++ b/libr/core/cmd.c @@ -6761,6 +6761,9 @@ R_API char *r_core_cmd_str(RCore *core, const char *cmd) { if (--core->cons->context->cmd_str_depth == 0) { core->cons->context->noflush = false; } + if (core->cons->context->grep.strings) { + R_LOG_WARN ("cmd_str grep strings len: %d", r_list_length (core->cons->context->grep.strings)); + } r_cons_filter (core->cons); const char *static_str = r_cons_get_buffer (core->cons, NULL); char *retstr = strdup (r_str_get (static_str)); diff --git a/libr/core/cmd_anal.inc.c b/libr/core/cmd_anal.inc.c index 72c90738eb8a6..c55e7d364782f 100644 --- a/libr/core/cmd_anal.inc.c +++ b/libr/core/cmd_anal.inc.c @@ -16063,6 +16063,7 @@ static int cmd_anal(void *data, const char *input) { const char *r; RCore *core = (RCore *)data; ut32 tbs = core->blocksize; + ut64 addr = core->addr; switch (input[0]) { case 0: // "a" r_core_cmd_call (core, "aai"); @@ -16203,17 +16204,22 @@ static int cmd_anal(void *data, const char *input) { } break; case 'k': // "adk" - r = r_anal_data_kind (core->anal, core->addr, core->block, core->blocksize); - r_cons_println (core->cons, r); + { + ut8 *data = calloc (tbs + 1, 1); + r_io_read_at (core->io, addr, data, tbs); + r = r_anal_data_kind (core->anal, addr, data, tbs); + r_cons_println (core->cons, r); + free (data); + } break; case '\0': // "ad" - r_core_anal_data (core, core->addr, 2 + (core->blocksize / 4), 1, 0); + r_core_anal_data (core, core->addr, 2 + (tbs / 4), 1, 0); break; case '4': // "ad4" - r_core_anal_data (core, core->addr, 2 + (core->blocksize / 4), 1, 4); + r_core_anal_data (core, core->addr, 2 + (tbs / 4), 1, 4); break; case '8': // "ad8" - r_core_anal_data (core, core->addr, 2 + (core->blocksize / 4), 1, 8); + r_core_anal_data (core, core->addr, 2 + (tbs / 4), 1, 8); break; case '?': r_core_cmd_help (core, help_msg_ad); diff --git a/libr/core/cmd_print.inc.c b/libr/core/cmd_print.inc.c index 760c4bf8e870f..78d3f5f5b7dc7 100644 --- a/libr/core/cmd_print.inc.c +++ b/libr/core/cmd_print.inc.c @@ -8533,10 +8533,14 @@ static int cmd_print(void *data, const char *input) { ut64 from = r_config_get_i (core->config, "diff.from"); ut64 to = r_config_get_i (core->config, "diff.to"); if (from == to && !from) { - r_core_block_size (core, len); - len = core->blocksize; - r_print_hexdump (core->print, core->addr, - core->block, core->blocksize, 16, 1, 1); + ut8 *data = calloc (1, len + 1); + if (data) { + r_io_read_at (core->io, core->addr, data, len); + r_core_block_size (core, len); + r_print_hexdump (core->print, core->addr, + data, len, 16, 1, 1); + free (data); + } } else { r_core_print_cmp (core, from, to); } diff --git a/libr/core/core.c b/libr/core/core.c index 6afed83d60ff4..c8602423e45d9 100644 --- a/libr/core/core.c +++ b/libr/core/core.c @@ -2839,7 +2839,6 @@ R_API void r_core_fini(RCore *c) { // avoid double free r_list_free (c->ropchain); r_table_free (c->table); - r_event_free (c->ev); R_FREE (c->cmdlog); free (c->lastsearch); r_list_free (c->cmdqueue); @@ -2860,6 +2859,7 @@ R_API void r_core_fini(RCore *c) { r_list_free (c->watchers); r_list_free (c->scriptstack); r_core_task_scheduler_fini (&c->tasks); + r_event_free (c->ev); // Free cmd and its plugins before freeing event system c->rcmd = r_cmd_free (c->rcmd); r_lib_free (c->lib); diff --git a/libr/core/task.c b/libr/core/task.c index 57a7783654775..4ca506a76de7b 100644 --- a/libr/core/task.c +++ b/libr/core/task.c @@ -13,6 +13,22 @@ static int _task_run_forked(RCoreTaskScheduler *scheduler, RCoreTask *task); #define CUSTOMCORE 0 static RCore *mycore_new(RCore *core) { + // For task threads (non-main tasks), create a separate RCore with its own RCons + if (task_tls_current && task_tls_current != core->tasks.main_task) { + RCore *c = R_NEW (RCore); + if (!c) { + return core; + } + memcpy (c, core, sizeof (RCore)); + c->cons = r_cons_new (); + if (!c->cons) { + free (c); + return core; + } + // XXX: RConsBind must disappear. its used in bin, fs and search + // TODO: use r_cons_clone instead + return c; + } #if CUSTOMCORE RCore *c = R_NEW (RCore); memcpy (c, core, sizeof (RCore)); @@ -26,11 +42,67 @@ static RCore *mycore_new(RCore *core) { } static void mycore_free(RCore *a) { + if (a && a->cons) { + // If this is a task-specific core (has its own cons), free it but not the context + RCons *global_cons = r_cons_singleton(); + if (a->cons != global_cons) { + a->cons->context = NULL; // Don't free the shared context + r_cons_free (a->cons); + free (a); + return; + } + } #if CUSTOMCORE r_cons_free (a->cons); #endif } +static RCons *task_cons_create(RCons *base, RConsContext *task_ctx, bool *attached_ctx_out) { + RCons *cons = r_cons_new2 (); + if (!cons) { + return NULL; + } + cons->use_utf8 = base->use_utf8; + cons->use_utf8_curvy = base->use_utf8_curvy; + cons->dotted_lines = base->dotted_lines; + cons->break_lines = base->break_lines; + cons->vtmode = base->vtmode; + cons->linesleep = base->linesleep; + cons->pagesize = base->pagesize; + cons->maxpage = base->maxpage; + cons->mouse = base->mouse; + cons->timeout = base->timeout; + cons->otimeout = base->otimeout; + cons->null = base->null; + cons->rgbstr = base->rgbstr; + cons->enable_highlight = base->enable_highlight; + cons->fdout = base->fdout; + cons->click_set = base->click_set; + cons->click_x = base->click_x; + cons->click_y = base->click_y; + + if (task_ctx) { + RConsContext *owned_ctx = cons->context; + cons->context = task_ctx; + r_cons_context_free (owned_ctx); + if (attached_ctx_out) { + *attached_ctx_out = true; + } + } else if (base->context) { + RConsContext *owned_ctx = cons->context; + cons->context = r_cons_context_clone (base->context); + r_cons_context_free (owned_ctx); + if (!cons->context) { + r_cons_free2 (cons); + return NULL; + } + if (attached_ctx_out) { + *attached_ctx_out = false; + } + } + return cons; +} + R_API void r_core_task_scheduler_init(RCoreTaskScheduler *tasks, RCore *core) { tasks->task_id_next = 0; tasks->tasks = r_list_newf (free); @@ -471,20 +543,53 @@ static RThreadFunctionRet task_run(RCoreTask *task) { r_event_send (core->ev, R_EVENT_CORE_TASK_STARTED, task); } + RCore *exec_core = task->task_core? task->task_core: core; + RCons *saved_cons = exec_core->cons; + RCons *task_cons = NULL; + bool attached_ctx = false; + bool interrupted = false; + if (task->cons_context && task->cons_context->breaked) { - // breaked in R_CORE_TASK_STATE_BEFORE_START goto stillbirth; } - RCore *local_core = mycore_new (core); - char *res_str; + if (task != scheduler->main_task) { + task_cons = task_cons_create (saved_cons, task->cons_context, &attached_ctx); + if (task_cons) { + r_cons_global (task_cons); + exec_core->cons = task_cons; + r_core_bind_cons (exec_core); + } + } + + if (task->cons_context) { + interrupted = task->cons_context->breaked; + } else if (task_cons && task_cons->context) { + interrupted = task_cons->context->breaked; + } + + char *res_str = NULL; if (task == scheduler->main_task) { - r_core_cmd (local_core, task->cmd, task->cmd_log); - res_str = NULL; + r_core_cmd (exec_core, task->cmd, task->cmd_log); } else { - res_str = r_core_cmd_str (local_core, task->cmd); + res_str = r_core_cmd_str (exec_core, task->cmd); + } + + if (task->cons_context) { + interrupted = task->cons_context->breaked; + } else if (task_cons && task_cons->context) { + interrupted = task_cons->context->breaked; + } + + if (task_cons) { + exec_core->cons = saved_cons; + r_core_bind_cons (exec_core); + r_cons_global (saved_cons); + if (attached_ctx) { + task_cons->context = NULL; + } + r_cons_free2 (task_cons); } - mycore_free (local_core); free (task->res); task->res = res_str; @@ -501,11 +606,7 @@ static RThreadFunctionRet task_run(RCoreTask *task) { task_end (task); - // Determine interruption vs finished - bool interrupted = false; - if (task->cons_context && task->cons_context->breaked) { - interrupted = true; - } + // Determine interruption vs finished (already captured above) if (task->cb) { task->cb (task->user, task->res); @@ -549,6 +650,8 @@ static RThreadFunctionRet task_run_thread(RThread *th) { RCoreTask *task = (RCoreTask *)th->user; // Set TLS current task for this thread during execution task_tls_current = task; + // Initialize thread-local RCons for this task thread + r_cons_thready (); RThreadFunctionRet ret = task_run (task); // Clear TLS on exit task_tls_current = NULL;