Skip to content

Commit

Permalink
$: Fix $alias=$<backtick>cmd<backtick> (#4293)
Browse files Browse the repository at this point in the history
  • Loading branch information
kazarmy authored Feb 24, 2024
1 parent 7225e9b commit b61b951
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 11 deletions.
51 changes: 42 additions & 9 deletions librz/core/cmd/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -3597,7 +3597,8 @@ static bool substitute_args(struct tsr2cmd_state *state, TSNode args, TSNode *ne
return res;
}

static RzCmdParsedArgs *ts_node_handle_arg_prargs(struct tsr2cmd_state *state, TSNode command, TSNode arg, uint32_t child_idx, bool do_unwrap) {
static RzCmdParsedArgs *ts_node_handle_arg_prargs(struct tsr2cmd_state *state, TSNode command, TSNode arg, uint32_t child_idx, bool do_unwrap,
char **new_command_str, bool *has_space_after_new_cmd) {
RzCmdParsedArgs *res = NULL;
TSNode new_command;
substitute_args_init(state, command);
Expand All @@ -3607,6 +3608,21 @@ static RzCmdParsedArgs *ts_node_handle_arg_prargs(struct tsr2cmd_state *state, T
goto err;
}

if (new_command_str || has_space_after_new_cmd) {
TSNode new_command_node = ts_node_child_by_field_name(new_command, "command", strlen("command"));
if (ts_node_is_null(new_command_node)) {
goto err;
}
if (new_command_str) {
*new_command_str = ts_node_sub_string(new_command_node, state->input);
}
if (has_space_after_new_cmd) {
TSNode args_node = ts_node_child_by_field_name(new_command, "args", strlen("args"));
*has_space_after_new_cmd = !ts_node_is_null(args_node) &&
ts_node_end_byte(new_command_node) < ts_node_start_byte(args_node);
}
}

arg = ts_node_named_child(new_command, child_idx);
res = parse_args(state, arg, do_unwrap);
if (res == NULL) {
Expand All @@ -3619,7 +3635,7 @@ static RzCmdParsedArgs *ts_node_handle_arg_prargs(struct tsr2cmd_state *state, T
}

static char *ts_node_handle_arg(struct tsr2cmd_state *state, TSNode command, TSNode arg, uint32_t child_idx) {
RzCmdParsedArgs *a = ts_node_handle_arg_prargs(state, command, arg, child_idx, true);
RzCmdParsedArgs *a = ts_node_handle_arg_prargs(state, command, arg, child_idx, true, NULL, NULL);
char *str = rz_cmd_parsed_args_argstr(a);
rz_cmd_parsed_args_free(a);
return str;
Expand Down Expand Up @@ -3668,6 +3684,7 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(arged_stmt) {
RZ_LOG_DEBUG("arged_stmt command: '%s'\n", command_str);
TSNode args = ts_node_child_by_field_name(node, "args", strlen("args"));
RzCmdStatus res = RZ_CMD_STATUS_INVALID;
bool has_space_after_cmd = !ts_node_is_null(args) && ts_node_end_byte(command) < ts_node_start_byte(args);

// FIXME: this special handling should be removed once we have a proper
// command tree
Expand All @@ -3686,7 +3703,23 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(arged_stmt) {
if (!ts_node_is_null(args)) {
RzCmdDesc *cd = rz_cmd_get_desc(state->core->rcmd, command_str);
bool do_unwrap = cd && cd->type != RZ_CMD_DESC_TYPE_OLDINPUT;
pr_args = ts_node_handle_arg_prargs(state, node, args, 1, do_unwrap);
if (rz_str_startswith(command_str, "$") && strstr(command_str, "=$")) {
// Special handling for $alias=$`cmd`. For current code
// to work properly, "command_str" has to change after
// substitution to include the first token of `cmd`.
//
// FIXME: Convert to rzshell and/or simplify syntax.
char *new_command_str = NULL;
pr_args = ts_node_handle_arg_prargs(state, node, args, 1, do_unwrap,
&new_command_str, &has_space_after_cmd);
if (!new_command_str) {
goto err;
}
free(command_str);
command_str = new_command_str;
} else {
pr_args = ts_node_handle_arg_prargs(state, node, args, 1, do_unwrap, NULL, NULL);
}
if (!pr_args) {
goto err;
}
Expand All @@ -3699,7 +3732,7 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(arged_stmt) {
}

pr_args->extra = command_extra_str;
pr_args->has_space_after_cmd = !ts_node_is_null(args) && ts_node_end_byte(command) < ts_node_start_byte(args);
pr_args->has_space_after_cmd = has_space_after_cmd;
res = rz_cmd_call_parsed_args(state->core->rcmd, pr_args);
if (res == RZ_CMD_STATUS_WRONG_ARGS) {
const char *cmdname = rz_cmd_parsed_args_cmd(pr_args);
Expand Down Expand Up @@ -3999,7 +4032,7 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(help_stmt) {
if (!ts_node_is_null(args)) {
RzCmdDesc *cd = rz_cmd_get_desc(state->core->rcmd, command_str);
bool do_unwrap = cd && cd->type != RZ_CMD_DESC_TYPE_OLDINPUT;
pr_args = ts_node_handle_arg_prargs(state, node, args, 1, do_unwrap);
pr_args = ts_node_handle_arg_prargs(state, node, args, 1, do_unwrap, NULL, NULL);
if (!pr_args) {
goto err_else;
}
Expand Down Expand Up @@ -4067,7 +4100,7 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(tmp_fromto_stmt) {
RzCore *core = state->core;
TSNode command = ts_node_named_child(node, 0);
TSNode fromto = ts_node_named_child(node, 1);
RzCmdParsedArgs *a = ts_node_handle_arg_prargs(state, node, fromto, 1, true);
RzCmdParsedArgs *a = ts_node_handle_arg_prargs(state, node, fromto, 1, true, NULL, NULL);
if (!a || a->argc != 2 + 1) {
rz_cmd_parsed_args_free(a);
return RZ_CMD_STATUS_INVALID;
Expand Down Expand Up @@ -4569,7 +4602,7 @@ static RzCmdStatus iter_offsets_common(struct tsr2cmd_state *state, TSNode node,

TSNode args = ts_node_named_child(node, 1);

RzCmdParsedArgs *a = ts_node_handle_arg_prargs(state, node, args, 1, true);
RzCmdParsedArgs *a = ts_node_handle_arg_prargs(state, node, args, 1, true, NULL, NULL);
if (!a || (has_size && (a->argc - 1) % 2 != 0)) {
RZ_LOG_ERROR("Cannot parse args\n");
rz_cmd_parsed_args_free(a);
Expand Down Expand Up @@ -4627,7 +4660,7 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(iter_instrs_stmt) {
DEFINE_HANDLE_TS_FCN_AND_SYMBOL(iter_step_stmt) {
TSNode command = ts_node_named_child(node, 0);
TSNode args = ts_node_named_child(node, 1);
RzCmdParsedArgs *a = ts_node_handle_arg_prargs(state, node, args, 1, true);
RzCmdParsedArgs *a = ts_node_handle_arg_prargs(state, node, args, 1, true, NULL, NULL);
if (!a || a->argc != 3 + 1) {
rz_cmd_parsed_args_free(a);
return RZ_CMD_STATUS_INVALID;
Expand Down Expand Up @@ -5160,7 +5193,7 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(pipe_stmt) {
TSNode command_pipe = ts_node_named_child(node, 1);

RzCmdStatus res = RZ_CMD_STATUS_INVALID;
RzCmdParsedArgs *a = ts_node_handle_arg_prargs(state, node, command_pipe, 1, true);
RzCmdParsedArgs *a = ts_node_handle_arg_prargs(state, node, command_pipe, 1, true, NULL, NULL);
if (a && a->argc > 1) {
res = core_cmd_pipe(state->core, state, command_rizin, a->argc - 1, a->argv + 1);
}
Expand Down
4 changes: 2 additions & 2 deletions test/db/archos/linux-x64/dbg_step_back
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dr rip
$rsp_after=$`dr rsp`
2dsb
dr rip
%v `dr rsp~[1]`-`$rsp_after~[0]`
%v `dr rsp~[1]`-`$rsp_after~[1]`
EOF
EXPECT=<<EOF
rip = 0x00000000004028b6
Expand All @@ -36,7 +36,7 @@ dsb
dsb
dr rax
dr rip
%v `dr rsp~[1]`-`$rsp_after~[0]`
%v `dr rsp~[1]`-`$rsp_after~[1]`
EOF
EXPECT=<<EOF
rax = 0x0000000000600980
Expand Down
15 changes: 15 additions & 0 deletions test/db/cmd/cmd_alias
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,18 @@ EXPECT=<<EOF
$foo
EOF
RUN

NAME=$alias=$`cmd`
FILE==
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
$copy=$`ar rax`
ar rax
$copy
EOF
EXPECT=<<EOF
rax = 0x0000000000000000
rax = 0x0000000000000000
EOF
RUN

0 comments on commit b61b951

Please sign in to comment.