Introduce escaping in grep specifiers (#16185)

* Introduce escaping in grep specifiers

Grep specifiers (the part after `~`) can accept a lot of characters.
However, some of those have a special meaning in some contexts and they
should be parsed for better consistency.

For example, `(` and `)` can have particular meanings inside a macro
definition and it's important to allow escaping to differentiate:

(foo; pd~hello)) -> parsing error, there are 2 closing parenthesis
(foo; pd~hello\)) -> user wants to grep for string 'hello)'

* Add some tests for escaped characters in grep specifier
This commit is contained in:
Riccardo Schirone 2020-03-12 11:28:45 +01:00 committed by GitHub
parent 89cda00652
commit 41cb001973
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 25 deletions

View File

@ -27,9 +27,18 @@
#include <sys/utsname.h>
#endif
// NOTE: this should be in sync with SPECIAL_CHARACTERS in
// radare2-shell-parser grammar, except for ", ' and
// whitespaces, because we let cmd_substitution_arg create
// new arguments
static const char *SPECIAL_CHARS_REGULAR = "@;~$#|`\"'()<>";
#if USE_TREESITTER
#include <tree_sitter/api.h>
TSLanguage *tree_sitter_r2cmd ();
static const char *SPECIAL_CHARS_DOUBLE_QUOTED = "\"";
static const char *SPECIAL_CHARS_SINGLE_QUOTED = "'";
#endif
R_API void r_save_panels_layout(RCore *core, const char *_name);
@ -2275,6 +2284,22 @@ static int cmd_system(void *data, const char *input) {
return ret;
}
static char *unescape_special_chars(char *s, const char *special_chars) {
char *dst = R_NEWS (char, strlen (s) + 1);
int i, j = 0;
for (i = 0; s[i]; i++) {
if (s[i] != '\\' || !strchr (special_chars, s[i + 1])) {
dst[j++] = s[i];
continue;
}
dst[j++] = s[i + 1];
i++;
}
dst[j++] = '\0';
return dst;
}
#if __WINDOWS__
#include <tchar.h>
#define __CLOSE_DUPPED_PIPES() \
@ -3706,6 +3731,9 @@ fuji:
rc = false;
}
beach:
if (grep) {
grep = unescape_special_chars (grep, SPECIAL_CHARS_REGULAR);
}
r_cons_grep_process (grep);
if (scr_html != -1) {
r_cons_flush ();
@ -4531,14 +4559,6 @@ DEFINE_IS_TS_FCN(double_quoted_arg)
DEFINE_IS_TS_FCN(single_quoted_arg)
DEFINE_IS_TS_FCN(concatenation)
// NOTE: this should be in sync with SPECIAL_CHARACTERS in
// radare2-shell-parser grammar, except for ", ' and
// whitespaces, because we let cmd_substitution_arg create
// new arguments
static const char *SPECIAL_CHARS_REGULAR = "@;~$#|`\"'()<>";
static const char *SPECIAL_CHARS_DOUBLE_QUOTED = "\"";
static const char *SPECIAL_CHARS_SINGLE_QUOTED = "'";
static struct tsr2cmd_edit *create_cmd_edit(struct tsr2cmd_state *state, TSNode arg, char *new_text) {
struct tsr2cmd_edit *e = R_NEW0 (struct tsr2cmd_edit);
ut32 command_start = ts_node_start_byte (state->substitute_cmd);
@ -4584,22 +4604,6 @@ static char *escape_special_chars(char *s, const char *special_chars) {
return d;
}
static char *unescape_special_chars(char *s, const char *special_chars) {
char *dst = R_NEWS (char, strlen (s) + 1);
int i, j = 0;
for (i = 0; s[i]; i++) {
if (s[i] != '\\' || !strchr (special_chars, s[i + 1])) {
dst[j++] = s[i];
continue;
}
dst[j++] = s[i + 1];
i++;
}
dst[j++] = '\0';
return dst;
}
void free_tsr2cmd_edit(struct tsr2cmd_edit *edit) {
free (edit->new_text);
free (edit->old_text);
@ -5871,6 +5875,7 @@ DEFINE_HANDLE_TS_FCN(grep_command) {
r_strbuf_prepend (sb, "~");
char *specifier_str = r_cons_grep_strip (r_strbuf_get (sb), "`");
r_strbuf_free (sb);
specified_str = unescape_special_chars (specifier_str, SPECIAL_CHARS_REGULAR);
R_LOG_DEBUG ("grep_command processed specifier: '%s'\n", specifier_str);
r_cons_grep_process (specifier_str);
free (arg_str);

View File

@ -285,3 +285,25 @@ EXPECT=<<EOF
1
EOF
RUN
NAME=escaped chars
CMDS=<<EOF
?e Hello\x40World~Hello\@
?e Hello\x24World~Hello\@
?e Hello\n\x23World~\#
EOF
EXPECT=<<EOF
Hello@World
#World
EOF
RUN
NAME=escaped chars 2
BROKEN=1
CMDS=<<EOF
?e Hello\n\x3bWorld~\;
EOF
EXPECT=<<EOF
;World
EOF
RUN

View File

@ -75,7 +75,7 @@ RUN
NAME=radiff2 -AC (mach0 fat files)
FILE=-
CMDS=!!radiff2 -AC ../bins/other/radiff2/hellocxx-osx-fat-intel_1 ../bins/other/radiff2/hellocxx-osx-fat-intel_2~?(1.000000)
CMDS=!!radiff2 -AC ../bins/other/radiff2/hellocxx-osx-fat-intel_1 ../bins/other/radiff2/hellocxx-osx-fat-intel_2~?\(1.000000\)
EXPECT=<<EOF
17
EOF