1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
/* Functions to deal with the inferior being executed on GDB or
GDBserver.
Copyright (C) 2019-2024 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "gdbsupport/common-inferior.h"
/* See common-inferior.h. */
bool startup_with_shell = true;
/* 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. */
static std::string
escape_characters (const char *arg, const char *special)
{
gdb_assert (special != nullptr);
gdb_assert (arg != nullptr);
std::string result;
#ifdef __MINGW32__
static const char quote = '"';
#else
static const char quote = '\'';
#endif
/* 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__
if (*cp == quote)
#else
if (strchr (special, *cp) != nullptr)
#endif
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__
/* This holds all the characters considered special to the
Windows shells. */
static const char special[] = "\"!&*|[]{}<>?`~^=;, \t\n";
#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";
#endif
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__
static const char special[] = "\" \t\n";
#else
static const char special[] = "\"' \t\n";
#endif
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)
{
if (!result.empty ())
result += " ";
result += escape_func (a);
}
return result;
}
|