Git: BranchModel: More checks to guard against crashes

Task-number: QTCREATORBUG-32186
Change-Id: If4f0cf990a4eb7c0cadcf8c50cff1211852719b8
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Andre Hartmann
2025-03-19 09:16:35 +01:00
committed by André Hartmann
parent c95ab42eef
commit 11d956b346

View File

@@ -89,6 +89,8 @@ public:
bool childOfRoot(RootNodes root) const bool childOfRoot(RootNodes root) const
{ {
BranchNode *rn = rootNode(); BranchNode *rn = rootNode();
QTC_ASSERT(rn, return false);
if (rn->isLeaf()) if (rn->isLeaf())
return false; return false;
if (root >= rn->children.count()) if (root >= rn->children.count())
@@ -222,9 +224,9 @@ public:
void flushOldEntries(); void flushOldEntries();
void updateAllUpstreamStatus(BranchNode *node); void updateAllUpstreamStatus(BranchNode *node);
BranchModel *q; BranchModel *q = nullptr;
FilePath workingDirectory; FilePath workingDirectory;
BranchNode *rootNode; BranchNode *rootNode = nullptr;
BranchNode *currentBranch = nullptr; BranchNode *currentBranch = nullptr;
BranchNode *headNode = nullptr; BranchNode *headNode = nullptr;
QString currentSha; QString currentSha;
@@ -269,6 +271,7 @@ QModelIndex BranchModel::index(int row, int column, const QModelIndex &parentIdx
if (column > 1) if (column > 1)
return {}; return {};
BranchNode *parentNode = indexToNode(parentIdx); BranchNode *parentNode = indexToNode(parentIdx);
QTC_ASSERT(parentNode, return {});
if (row >= parentNode->count()) if (row >= parentNode->count())
return {}; return {};
@@ -292,7 +295,10 @@ int BranchModel::rowCount(const QModelIndex &parentIdx) const
if (parentIdx.column() > 0) if (parentIdx.column() > 0)
return 0; return 0;
return indexToNode(parentIdx)->count(); const BranchNode *node = indexToNode(parentIdx);
QTC_ASSERT(node, return 0);
return node->count();
} }
int BranchModel::columnCount(const QModelIndex &parent) const int BranchModel::columnCount(const QModelIndex &parent) const
@@ -394,6 +400,8 @@ Qt::ItemFlags BranchModel::flags(const QModelIndex &index) const
void BranchModel::clear() void BranchModel::clear()
{ {
for (BranchNode *root : std::as_const(d->rootNode->children)) { for (BranchNode *root : std::as_const(d->rootNode->children)) {
QTC_ASSERT(root, continue);
while (root->count()) while (root->count())
delete root->children.takeLast(); delete root->children.takeLast();
} }
@@ -464,6 +472,7 @@ void BranchModel::refresh(const FilePath &workingDirectory, ShowError showError)
} }
if (!d->currentBranch) { if (!d->currentBranch) {
BranchNode *local = d->rootNode->children.at(LocalBranches); BranchNode *local = d->rootNode->children.at(LocalBranches);
QTC_ASSERT(local, return);
d->currentBranch = d->headNode = new BranchNode( d->currentBranch = d->headNode = new BranchNode(
Tr::tr("Detached HEAD"), "HEAD", {}, d->currentDateTime); Tr::tr("Detached HEAD"), "HEAD", {}, d->currentDateTime);
local->prepend(d->headNode); local->prepend(d->headNode);
@@ -484,6 +493,8 @@ void BranchModel::setCurrentBranch()
return; return;
BranchNode *local = d->rootNode->children.at(LocalBranches); BranchNode *local = d->rootNode->children.at(LocalBranches);
QTC_ASSERT(local, return);
const QStringList branchParts = currentBranch.split('/'); const QStringList branchParts = currentBranch.split('/');
for (const QString &branchPart : branchParts) { for (const QString &branchPart : branchParts) {
local = local->childOfName(branchPart); local = local->childOfName(branchPart);
@@ -602,7 +613,10 @@ bool BranchModel::isTag(const QModelIndex &idx) const
{ {
if (!idx.isValid() || !d->hasTags()) if (!idx.isValid() || !d->hasTags())
return false; return false;
return indexToNode(idx)->isTag(); const BranchNode *node = indexToNode(idx);
QTC_ASSERT(node, return false);
return node->isTag();
} }
void BranchModel::removeBranch(const QModelIndex &idx) void BranchModel::removeBranch(const QModelIndex &idx)
@@ -718,6 +732,8 @@ QModelIndex BranchModel::addBranch(const QString &name, bool track, const QModel
} }
BranchNode *local = d->rootNode->children.at(LocalBranches); BranchNode *local = d->rootNode->children.at(LocalBranches);
QTC_ASSERT(local, return {});
const int slash = name.indexOf('/'); const int slash = name.indexOf('/');
const QString leafName = slash == -1 ? name : name.mid(slash + 1); const QString leafName = slash == -1 ? name : name.mid(slash + 1);
bool added = false; bool added = false;
@@ -766,6 +782,8 @@ void BranchModel::setOldBranchesIncluded(bool value)
std::optional<QString> BranchModel::remoteName(const QModelIndex &idx) const std::optional<QString> BranchModel::remoteName(const QModelIndex &idx) const
{ {
const BranchNode *remotesNode = d->rootNode->children.at(RemoteBranches); const BranchNode *remotesNode = d->rootNode->children.at(RemoteBranches);
QTC_ASSERT(remotesNode, return std::nullopt);
const BranchNode *node = indexToNode(idx); const BranchNode *node = indexToNode(idx);
if (!node) if (!node)
return std::nullopt; return std::nullopt;
@@ -828,6 +846,8 @@ void BranchModel::Private::parseOutputLine(const QString &line, bool force)
rootType = RemoteBranches; rootType = RemoteBranches;
const QString remoteName = nameParts.at(1); const QString remoteName = nameParts.at(1);
root = rootNode->children.at(rootType); root = rootNode->children.at(rootType);
QTC_ASSERT(root, return);
oldEntriesRoot = root->childOfName(remoteName); oldEntriesRoot = root->childOfName(remoteName);
if (!oldEntriesRoot) if (!oldEntriesRoot)
oldEntriesRoot = root->append(new BranchNode(remoteName)); oldEntriesRoot = root->append(new BranchNode(remoteName));
@@ -843,6 +863,7 @@ void BranchModel::Private::parseOutputLine(const QString &line, bool force)
if (!oldEntriesRoot) if (!oldEntriesRoot)
oldEntriesRoot = root; oldEntriesRoot = root;
if (isOld) { if (isOld) {
QTC_ASSERT(oldEntriesRoot, return);
if (oldEntriesRoot->children.size() > Constants::MAX_OBSOLETE_COMMITS_TO_DISPLAY) if (oldEntriesRoot->children.size() > Constants::MAX_OBSOLETE_COMMITS_TO_DISPLAY)
return; return;
if (currentRoot != oldEntriesRoot) { if (currentRoot != oldEntriesRoot) {
@@ -869,6 +890,7 @@ void BranchModel::Private::parseOutputLine(const QString &line, bool force)
const QString name = nameParts.last(); const QString name = nameParts.last();
nameParts.removeLast(); nameParts.removeLast();
QTC_ASSERT(root, return);
auto newNode = new BranchNode(name, sha, upstream, dateTime); auto newNode = new BranchNode(name, sha, upstream, dateTime);
root->insert(nameParts, newNode); root->insert(nameParts, newNode);
if (current) if (current)
@@ -900,6 +922,7 @@ QModelIndex BranchModel::nodeToIndex(BranchNode *node, int column) const
{ {
if (node == d->rootNode) if (node == d->rootNode)
return {}; return {};
QTC_ASSERT(node, return {});
QTC_ASSERT(node->parent, return {}); QTC_ASSERT(node->parent, return {});
return createIndex(node->parent->rowOf(node), column, static_cast<void *>(node)); return createIndex(node->parent->rowOf(node), column, static_cast<void *>(node));
@@ -913,6 +936,7 @@ void BranchModel::removeNode(const QModelIndex &idx)
while (node->count() == 0 && node->parent != d->rootNode) { while (node->count() == 0 && node->parent != d->rootNode) {
BranchNode *parentNode = node->parent; BranchNode *parentNode = node->parent;
QTC_ASSERT(node, return);
const QModelIndex parentIndex = nodeToIndex(parentNode, ColumnBranch); const QModelIndex parentIndex = nodeToIndex(parentNode, ColumnBranch);
const int nodeRow = nodeIndex.row(); const int nodeRow = nodeIndex.row();
beginRemoveRows(parentIndex, nodeRow, nodeRow); beginRemoveRows(parentIndex, nodeRow, nodeRow);
@@ -926,7 +950,7 @@ void BranchModel::removeNode(const QModelIndex &idx)
void BranchModel::updateUpstreamStatus(BranchNode *node) void BranchModel::updateUpstreamStatus(BranchNode *node)
{ {
if (!node->isLocal()) if (!node || !node->isLocal())
return; return;
Process *process = new Process(node); Process *process = new Process(node);