summaryrefslogtreecommitdiff
path: root/src/plugins/debugger/debuggerprotocol.cpp
diff options
context:
space:
mode:
authorhjk <hjk@qt.io>2020-08-12 00:18:00 +0200
committerhjk <hjk@qt.io>2020-10-06 07:01:04 +0000
commitf08c3d150af86a4c0760054e5b6cdbff023f8634 (patch)
tree2dc03c62a3956318f7bef3dca271ef78c33a0fd8 /src/plugins/debugger/debuggerprotocol.cpp
parentee5feb4939007a1114c420dcac808b4398c19855 (diff)
downloadqt-creator-f08c3d150af86a4c0760054e5b6cdbff023f8634.tar.gz
Debugger: Fix parsing of octal-encoded gdb escapes
Fixes: QTCREATORBUG-24462 Change-Id: I89153a04eeef6a2e20fefef45e0efa3712ec0997 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/debugger/debuggerprotocol.cpp')
-rw-r--r--src/plugins/debugger/debuggerprotocol.cpp181
1 files changed, 94 insertions, 87 deletions
diff --git a/src/plugins/debugger/debuggerprotocol.cpp b/src/plugins/debugger/debuggerprotocol.cpp
index ccd834636c..b62931705f 100644
--- a/src/plugins/debugger/debuggerprotocol.cpp
+++ b/src/plugins/debugger/debuggerprotocol.cpp
@@ -89,104 +89,111 @@ void GdbMi::parseResultOrValue(const QChar *&from, const QChar *to)
}
}
+// Reads one \ooo entity.
+static bool parseOctalEscapedHelper(const QChar *&from, const QChar *to, QByteArray &buffer)
+{
+ if (to - from < 4)
+ return false;
+ if (*from != '\\')
+ return false;
+
+ const char c1 = from[1].unicode();
+ const char c2 = from[2].unicode();
+ const char c3 = from[3].unicode();
+ if (!isdigit(c1) || !isdigit(c2) || !isdigit(c3))
+ return false;
+
+ buffer += char((c1 - '0') * 64 + (c2 - '0') * 8 + (c3 - '0'));
+ from += 4;
+ return true;
+}
+
+static bool parseHexEscapedHelper(const QChar *&from, const QChar *to, QByteArray &buffer)
+{
+ if (to - from < 4)
+ return false;
+ if (from[0]!= '\\')
+ return false;
+ if (from[1] != 'x')
+ return false;
+
+ const char c1 = from[2].unicode();
+ const char c2 = from[3].unicode();
+ if (!isxdigit(c1) || !isxdigit(c2))
+ return false;
+
+ buffer += char(16 * fromhex(c1) + fromhex(c2));
+ from += 4;
+ return true;
+}
+
+static void parseSimpleEscape(const QChar *&from, const QChar *to, QString &result)
+{
+ if (from == to) {
+ qDebug() << "MI Parse Error, unterminated backslash escape";
+ return;
+ }
+
+ QChar c = *from++;
+ switch (c.unicode()) {
+ case 'a': result += '\a'; break;
+ case 'b': result += '\b'; break;
+ case 'f': result += '\f'; break;
+ case 'n': result += '\n'; break;
+ case 'r': result += '\r'; break;
+ case 't': result += '\t'; break;
+ case 'v': result += '\v'; break;
+ case '"': result += '"'; break;
+ case '\'': result += '\''; break;
+ case '\\': result += '\\'; break;
+ default:
+ qDebug() << "MI Parse Error, unrecognized backslash escape";
+ }
+}
+
+// Reads subsequent \123 or \x12 entities and converts to Utf8,
+// *or* one escaped char, *or* one unescaped char.
+static void parseCharOrEscape(const QChar *&from, const QChar *to, QString &result)
+{
+ QByteArray buffer;
+ while (parseOctalEscapedHelper(from, to, buffer))
+ ;
+ while (parseHexEscapedHelper(from, to, buffer))
+ ;
+
+ if (!buffer.isEmpty())
+ result.append(QString::fromUtf8(buffer));
+ else if (*from == '\\')
+ parseSimpleEscape(++from, to, result);
+ else
+ result += *from++;
+}
+
QString GdbMi::parseCString(const QChar *&from, const QChar *to)
{
- QString result;
+ if (to == from)
+ return QString();
+
//qDebug() << "parseCString: " << QString(from, to - from);
if (*from != '"') {
qDebug() << "MI Parse Error, double quote expected";
++from; // So we don't hang
return QString();
}
- const QChar *ptr = from;
- ++ptr;
- while (ptr < to) {
- if (*ptr == '"') {
- ++ptr;
- result = QString(from + 1, ptr - from - 2);
- break;
- }
- if (*ptr == '\\') {
- ++ptr;
- if (ptr == to) {
- qDebug() << "MI Parse Error, unterminated backslash escape";
- from = ptr; // So we don't hang
- return QString();
- }
- }
- ++ptr;
- }
- from = ptr;
- int idx = result.indexOf('\\');
- if (idx >= 0) {
- QChar *dst = result.data() + idx;
- const QChar *src = dst + 1, *end = result.data() + result.length();
- do {
- QChar c = *src++;
- switch (c.unicode()) {
- case 'a': *dst++ = '\a'; break;
- case 'b': *dst++ = '\b'; break;
- case 'f': *dst++ = '\f'; break;
- case 'n': *dst++ = '\n'; break;
- case 'r': *dst++ = '\r'; break;
- case 't': *dst++ = '\t'; break;
- case 'v': *dst++ = '\v'; break;
- case '"': *dst++ = '"'; break;
- case '\\': *dst++ = '\\'; break;
- case 'x': {
- c = *src++;
- int chars = 0;
- uchar prod = 0;
- while (true) {
- uchar val = fromhex(c.unicode());
- if (val == UCHAR_MAX)
- break;
- prod = prod * 16 + val;
- if (++chars == 3 || src == end)
- break;
- c = *src++;
- }
- if (!chars) {
- qDebug() << "MI Parse Error, unrecognized hex escape";
- return QString();
- }
- *dst++ = prod;
- break;
- }
- default:
- {
- int chars = 0;
- uchar prod = 0;
- forever {
- if (c < '0' || c > '7') {
- --src;
- break;
- }
- prod = prod * 8 + c.unicode() - '0';
- if (++chars == 3 || src == end)
- break;
- c = *src++;
- }
- if (!chars) {
- qDebug() << "MI Parse Error, unrecognized backslash escape";
- return QString();
- }
- *dst++ = prod;
- }
- }
- while (src != end) {
- QChar c = *src++;
- if (c == '\\')
- break;
- *dst++ = c;
- }
- } while (src != end);
- *dst = 0;
- result.truncate(dst - result.data());
+ ++from; // Skip initial quote.
+ QString result;
+ result.reserve(to - from);
+ while (from < to) {
+ if (*from == '"') {
+ ++from;
+ return result;
+ }
+ parseCharOrEscape(from, to, result);
}
- return result;
+ qDebug() << "MI Parse Error, unfinished string";
+ return QString();
}
void GdbMi::parseValue(const QChar *&from, const QChar *to)