Skip to content

Commit 6b7238b

Browse files
radaretrufae
authored andcommitted
Preserve shell preprocessing and internal pipe chains ##shell
1 parent 0481255 commit 6b7238b

3 files changed

Lines changed: 53 additions & 9 deletions

File tree

libr/core/cmd.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4398,6 +4398,27 @@ static char *find_unescaped_conditional(char *cmd, const char *quotes) {
43984398
return or;
43994399
}
44004400

4401+
static bool is_internal_pipe_segment(const char *pipe, const char *next) {
4402+
const char *segment = pipe + 1;
4403+
size_t length = next - segment;
4404+
while (length > 0 && IS_WHITECHAR (segment[length - 1])) {
4405+
length--;
4406+
}
4407+
return length == 0 || (length == 1 && strchr ("DEJHT.?", *segment));
4408+
}
4409+
4410+
static char *find_unescaped_system_pipe(char *cmd, const char *quotes) {
4411+
char *pipe = (char *)r_str_firstbut_escape (cmd, '|', quotes);
4412+
while (pipe) {
4413+
char *next = (char *)r_str_firstbut_escape (pipe + 1, '|', quotes);
4414+
if (!next || !is_internal_pipe_segment (pipe, next)) {
4415+
return pipe;
4416+
}
4417+
pipe = next;
4418+
}
4419+
return NULL;
4420+
}
4421+
44014422
static void unescape_shell_control_operators(char *cmd) {
44024423
char quote = 0;
44034424
char *src = cmd;
@@ -4410,7 +4431,7 @@ static void unescape_shell_control_operators(char *cmd) {
44104431
continue;
44114432
}
44124433
if (!quote && (src[1] == '&' || src[1] == '|') &&
4413-
src[2] == '\\' && src[3] == src[1]) {
4434+
src[2] && src[3] && src[2] == '\\' && src[3] == src[1]) {
44144435
*dst++ = src[1];
44154436
*dst++ = src[1];
44164437
src += 4;
@@ -4769,16 +4790,12 @@ static int r_core_cmd_subst_i(RCore *core, char *cmd, char *colon, bool *tmpseek
47694790
return ret;
47704791
}
47714792
}
4772-
if (*cmd == '!') {
4773-
ret = r_cmd_call (core->rcmd, cmd);
4774-
r_list_free (tmpenvs);
4775-
return ret;
4776-
}
4793+
const bool system_command = *cmd == '!';
47774794
char *backtick = find_subcmd_begin (cmd, NULL);
47784795
if (backtick) {
47794796
goto escape_redir;
47804797
}
4781-
ptr = find_unescaped_conditional (cmd, quotestr);
4798+
ptr = system_command? NULL: find_unescaped_conditional (cmd, quotestr);
47824799
if (ptr) {
47834800
bool run = true;
47844801
for (;;) {
@@ -4806,8 +4823,8 @@ static int r_core_cmd_subst_i(RCore *core, char *cmd, char *colon, bool *tmpseek
48064823
}
48074824

48084825
/* pipe console to shell process */
4809-
char *raw_operator = (char *)r_str_lastbut (cmd, '|', quotestr);
4810-
ptr = (char *)r_str_firstbut_escape (cmd, '|', quotestr);
4826+
char *raw_operator = system_command? NULL: (char *)r_str_lastbut (cmd, '|', quotestr);
4827+
ptr = system_command? NULL: find_unescaped_system_pipe (cmd, quotestr);
48114828
if (!ptr && raw_operator && is_escaped_operator (cmd, raw_operator)) {
48124829
memmove (raw_operator - 1, raw_operator, strlen (raw_operator) + 1);
48134830
goto escape_pipe;
@@ -4885,6 +4902,9 @@ static int r_core_cmd_subst_i(RCore *core, char *cmd, char *colon, bool *tmpseek
48854902
}
48864903
}
48874904
escape_pipe:
4905+
if (system_command) {
4906+
goto escape_redir;
4907+
}
48884908
ptr = strstr (cmd, "?*");
48894909
if (ptr && ((ptr - cmd) == 0 || ((ptr - cmd) > 0 && ptr[-1] != '~'))) {
48904910
char *pipechar = strchr (ptr, '>');

test/db/cmd/cmd_system

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ PIPE
2929
EOF
3030
RUN
3131

32+
NAME=system commands keep r2 preprocessing
33+
FILE=-
34+
CMDS=<<EOF
35+
!!printf 'alpha\nbeta\n'~alpha
36+
!printf '%s\n' $(!printf nested)
37+
EOF
38+
EXPECT=<<EOF
39+
alpha
40+
nested
41+
EOF
42+
RUN
43+
3244
NAME=!| grep
3345
FILE=-
3446
CMDS=!echo fuck|grep bob

test/db/cmd/shell

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,18 @@ R2_SEMI
110110
EOF
111111
RUN
112112

113+
NAME=internal pipe transforms feed system pipelines
114+
FILE=malloc://32
115+
CMDS=<<EOF
116+
?e Zm9vCg== |D | grep foo
117+
?e foo |J | grep '"output":"foo\\n"'
118+
EOF
119+
EXPECT=<<EOF
120+
foo
121+
{"command":"?e foo","output":"foo\n","offset":0,"blocksize":256,"log":"","rc":0,"value":0}
122+
EOF
123+
RUN
124+
113125
NAME=touch
114126
FILE=malloc://32-
115127
CMDS=<<EOF

0 commit comments

Comments
 (0)