ClangCodeModel: Fix QStringView crashes

Some AST nodes have no range, triggering crashes in QStringView::mid().
Rather than checking all callers, we just use a safe variant.

Change-Id: I3c8d388693f9161249f201ecd4e8bad933463960
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2021-10-13 14:24:25 +02:00
parent 6bf7521a89
commit d9dd3612da

View File

@@ -98,6 +98,25 @@ static Q_LOGGING_CATEGORY(clangdLogHighlight, "qtc.clangcodemodel.clangd.highlig
static Q_LOGGING_CATEGORY(clangdLogTiming, "qtc.clangcodemodel.clangd.timing", QtWarningMsg); static Q_LOGGING_CATEGORY(clangdLogTiming, "qtc.clangcodemodel.clangd.timing", QtWarningMsg);
static QString indexingToken() { return "backgroundIndexProgress"; } static QString indexingToken() { return "backgroundIndexProgress"; }
static QStringView subView(const QString &s, qsizetype start)
{
if (start < 0 || start > s.length())
return {};
return QStringView(s).mid(start);
}
static QStringView subViewLen(const QString &s, qsizetype start, qsizetype length)
{
if (start < 0 || length < 0 || start + length > s.length())
return {};
return QStringView(s).mid(start, length);
}
static QStringView subViewEnd(const QString &s, qsizetype start, qsizetype end)
{
return subViewLen(s, start, end - start);
}
class AstNode : public JsonObject class AstNode : public JsonObject
{ {
public: public:
@@ -2197,7 +2216,7 @@ static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const
if (!wasIfdefedOut) if (!wasIfdefedOut)
rangeStartPos = doc->findBlockByNumber(it->line - 1).position(); rangeStartPos = doc->findBlockByNumber(it->line - 1).position();
const int pos = Utils::Text::positionInText(doc, it->line, it->column); const int pos = Utils::Text::positionInText(doc, it->line, it->column);
const QStringView content(QStringView(docContent).mid(pos, it->length).trimmed()); const QStringView content = subViewLen(docContent, pos, it->length).trimmed();
if (!content.startsWith(QLatin1String("#if")) if (!content.startsWith(QLatin1String("#if"))
&& !content.startsWith(QLatin1String("#elif")) && !content.startsWith(QLatin1String("#elif"))
&& !content.startsWith(QLatin1String("#else")) && !content.startsWith(QLatin1String("#else"))
@@ -2646,11 +2665,9 @@ bool ClangdClient::ClangdCompletionAssistProvider::isInCommentOrString(
const QString &line = tc.block().text(); const QString &line = tc.block().text();
const Token &idToken = tokens.at(1); const Token &idToken = tokens.at(1);
QStringView identifier = idToken.utf16charsEnd() > line.size() QStringView identifier = idToken.utf16charsEnd() > line.size()
? QStringView(line).mid( ? subView(line, idToken.utf16charsBegin())
idToken.utf16charsBegin()) : subViewLen(line, idToken.utf16charsBegin(),
: QStringView(line) idToken.utf16chars());
.mid(idToken.utf16charsBegin(),
idToken.utf16chars());
if (identifier == QLatin1String("include") if (identifier == QLatin1String("include")
|| identifier == QLatin1String("include_next") || identifier == QLatin1String("include_next")
|| (CppEditor::ProjectFile::isObjC(interface->filePath().toString()) || (CppEditor::ProjectFile::isObjC(interface->filePath().toString())
@@ -2944,7 +2961,7 @@ void ExtraHighlightingResultsCollector::insertAngleBracketInfo(int searchStart1,
int searchStart2, int searchEnd2) int searchStart2, int searchEnd2)
{ {
const int openingAngleBracketPos = onlyIndexOf( const int openingAngleBracketPos = onlyIndexOf(
QStringView(m_docContent).mid(searchStart1, searchEnd1 - searchStart1), subViewEnd(m_docContent, searchStart1, searchEnd1),
QStringView(QStringLiteral("<"))); QStringView(QStringLiteral("<")));
if (openingAngleBracketPos == -1) if (openingAngleBracketPos == -1)
return; return;
@@ -2954,7 +2971,7 @@ void ExtraHighlightingResultsCollector::insertAngleBracketInfo(int searchStart1,
if (searchStart2 >= searchEnd2) if (searchStart2 >= searchEnd2)
return; return;
const int closingAngleBracketPos = onlyIndexOf( const int closingAngleBracketPos = onlyIndexOf(
QStringView(m_docContent).mid(searchStart2, searchEnd2 - searchStart2), subViewEnd(m_docContent, searchStart2, searchEnd2),
QStringView(QStringLiteral(">"))); QStringView(QStringLiteral(">")));
if (closingAngleBracketPos == -1) if (closingAngleBracketPos == -1)
return; return;
@@ -3032,16 +3049,14 @@ void ExtraHighlightingResultsCollector::collectFromNode(const AstNode &node)
// sub-expressions 2 and 3. // sub-expressions 2 and 3.
const int searchStartPosQuestionMark = posForNodeEnd(children.first()); const int searchStartPosQuestionMark = posForNodeEnd(children.first());
const int searchEndPosQuestionMark = posForNodeStart(children.at(1)); const int searchEndPosQuestionMark = posForNodeStart(children.at(1));
QStringView content = QStringView(m_docContent).mid( QStringView content = subViewEnd(m_docContent, searchStartPosQuestionMark,
searchStartPosQuestionMark, searchEndPosQuestionMark);
searchEndPosQuestionMark - searchStartPosQuestionMark);
const int questionMarkPos = onlyIndexOf(content, QStringView(QStringLiteral("?"))); const int questionMarkPos = onlyIndexOf(content, QStringView(QStringLiteral("?")));
if (questionMarkPos == -1) if (questionMarkPos == -1)
return; return;
const int searchStartPosColon = posForNodeEnd(children.at(1)); const int searchStartPosColon = posForNodeEnd(children.at(1));
const int searchEndPosColon = posForNodeStart(children.at(2)); const int searchEndPosColon = posForNodeStart(children.at(2));
content = QStringView(m_docContent).mid(searchStartPosColon, content = subViewEnd(m_docContent, searchStartPosColon, searchEndPosColon);
searchEndPosColon - searchStartPosColon);
const int colonPos = onlyIndexOf(content, QStringView(QStringLiteral(":"))); const int colonPos = onlyIndexOf(content, QStringView(QStringLiteral(":")));
if (colonPos == -1) if (colonPos == -1)
return; return;
@@ -3218,8 +3233,7 @@ void ExtraHighlightingResultsCollector::collectFromNode(const AstNode &node)
if (isDeclaration) if (isDeclaration)
result.textStyles.mixinStyles.push_back(C_DECLARATION); result.textStyles.mixinStyles.push_back(C_DECLARATION);
const QStringView nodeText = QStringView(m_docContent) const QStringView nodeText = subViewEnd(m_docContent, nodeStartPos, nodeEndPos);
.mid(nodeStartPos, nodeEndPos - nodeStartPos);
if (isCallToNew || isCallToDelete) { if (isCallToNew || isCallToDelete) {
result.line = node.range().start().line() + 1; result.line = node.range().start().line() + 1;