aboutsummaryrefslogtreecommitdiff
path: root/gdbsupport/common-inferior.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gdbsupport/common-inferior.cc')
-rw-r--r--gdbsupport/common-inferior.cc175
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;