diff options
Diffstat (limited to 'gdbsupport/common-inferior.cc')
-rw-r--r-- | gdbsupport/common-inferior.cc | 175 |
1 files changed, 103 insertions, 72 deletions
diff --git a/gdbsupport/common-inferior.cc b/gdbsupport/common-inferior.cc index 4211e04..a07b556 100644 --- a/gdbsupport/common-inferior.cc +++ b/gdbsupport/common-inferior.cc @@ -1,7 +1,7 @@ /* Functions to deal with the inferior being executed on GDB or GDBserver. - Copyright (C) 2019-2024 Free Software Foundation, Inc. + Copyright (C) 2019-2025 Free Software Foundation, Inc. This file is part of GDB. @@ -24,100 +24,131 @@ bool startup_with_shell = true; -/* See common-inferior.h. */ +/* Escape characters in ARG and return an updated string. The string + SPECIAL contains the set of characters that must be escaped. SPECIAL + must not be nullptr, and it is assumed that SPECIAL contains the newline + '\n' character. It is assumed that ARG is not nullptr, but ARG can + be the empty string. */ -std::string -construct_inferior_arguments (gdb::array_view<char * const> argv) +static std::string +escape_characters (const char *arg, const char *special) { + gdb_assert (special != nullptr); + gdb_assert (arg != nullptr); + std::string result; - if (startup_with_shell) - { #ifdef __MINGW32__ - /* This holds all the characters considered special to the - Windows shells. */ - static const char special[] = "\"!&*|[]{}<>?`~^=;, \t\n"; - static const char quote = '"'; + static const char quote = '"'; #else - /* This holds all the characters considered special to the - typical Unix shells. We include `^' because the SunOS - /bin/sh treats it as a synonym for `|'. */ - static const char special[] = "\"!#$&*()\\|[]{}<>?'`~^; \t\n"; - static const char quote = '\''; + static const char quote = '\''; #endif - for (int i = 0; i < argv.size (); ++i) - { - if (i > 0) - result += ' '; - /* Need to handle empty arguments specially. */ - if (argv[i][0] == '\0') + /* Need to handle empty arguments specially. */ + if (arg[0] == '\0') + { + result += quote; + result += quote; + } + /* The special character handling code here assumes that if SPECIAL is + not nullptr, then SPECIAL will contain '\n'. This is true for all our + current usages, but if this ever changes in the future the following + might need reworking. */ + else + { +#ifdef __MINGW32__ + bool quoted = false; + + if (strpbrk (arg, special) != nullptr) + { + quoted = true; + result += quote; + } +#endif + for (const char *cp = arg; *cp; ++cp) + { + if (*cp == '\n') { + /* A newline cannot be quoted with a backslash (it just + disappears), only by putting it inside quotes. */ result += quote; + result += '\n'; result += quote; } else { #ifdef __MINGW32__ - bool quoted = false; - - if (strpbrk (argv[i], special)) - { - quoted = true; - result += quote; - } + if (*cp == quote) +#else + if (strchr (special, *cp) != nullptr) #endif - for (char *cp = argv[i]; *cp; ++cp) - { - if (*cp == '\n') - { - /* A newline cannot be quoted with a backslash (it - just disappears), only by putting it inside - quotes. */ - result += quote; - result += '\n'; - result += quote; - } - else - { + result += '\\'; + result += *cp; + } + } +#ifdef __MINGW32__ + if (quoted) + result += quote; +#endif + } + + return result; +} + +/* Return a version of ARG that has special shell characters escaped. */ + +static std::string +escape_shell_characters (const char *arg) +{ #ifdef __MINGW32__ - if (*cp == quote) + /* This holds all the characters considered special to the + Windows shells. */ + static const char special[] = "\"!&*|[]{}<>?`~^=;, \t\n"; #else - if (strchr (special, *cp) != NULL) + /* This holds all the characters considered special to the + typical Unix shells. We include `^' because the SunOS + /bin/sh treats it as a synonym for `|'. */ + static const char special[] = "\"!#$&*()\\|[]{}<>?'`~^; \t\n"; #endif - result += '\\'; - result += *cp; - } - } + + return escape_characters (arg, special); +} + +/* Return a version of ARG that has quote characters and white space + characters escaped. These are the characters that GDB sees as special + when splitting a string into separate arguments. */ + +static std::string +escape_gdb_characters (const char * arg) +{ #ifdef __MINGW32__ - if (quoted) - result += quote; + static const char special[] = "\" \t\n"; +#else + static const char special[] = "\"' \t\n"; #endif - } - } - } - else + + return escape_characters (arg, special); +} + +/* See common-inferior.h. */ + +std::string +construct_inferior_arguments (gdb::array_view<char * const> argv, + bool escape_shell_char) +{ + /* Select the desired escape function. */ + const auto escape_func = (escape_shell_char + ? escape_shell_characters + : escape_gdb_characters); + + std::string result; + + for (const char *a : argv) { - /* In this case we can't handle arguments that contain spaces, - tabs, or newlines -- see breakup_args(). */ - for (char *arg : argv) - { - char *cp = strchr (arg, ' '); - if (cp == NULL) - cp = strchr (arg, '\t'); - if (cp == NULL) - cp = strchr (arg, '\n'); - if (cp != NULL) - error (_("can't handle command-line " - "argument containing whitespace")); - } + if (!result.empty ()) + result += " "; - for (int i = 0; i < argv.size (); ++i) - { - if (i > 0) - result += " "; - result += argv[i]; - } + result += escape_func (a); } return result; |