diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2014-08-23 07:13:37 -0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2014-08-23 07:23:42 -0700 |
commit | fb371c063352715c84d2b3b85d16d6c0937b039b (patch) | |
tree | 47d7a689c532b0a3e278f015d3f48e514428fc78 | |
parent | 3e4c30735c835e8cc27ddbbffe3c4c61141f7d2e (diff) | |
download | subsurface-fb371c063352715c84d2b3b85d16d6c0937b039b.tar.gz |
TankBar: don't risk dereferencing stale pointers
Basically we could end up in a situation where the plotInfo is no longer
valid, yet the model changes and triggers a redraw before the new data is
passed into the TankBar.
Instead of chasing that race condition it seemed much easier to just copy
the plot_data entries and the gas information in the dive.
Fixes #716
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r-- | qt-ui/profile/tankitem.cpp | 27 | ||||
-rw-r--r-- | qt-ui/profile/tankitem.h | 5 |
2 files changed, 20 insertions, 12 deletions
diff --git a/qt-ui/profile/tankitem.cpp b/qt-ui/profile/tankitem.cpp index a5ec5050c..42692aacd 100644 --- a/qt-ui/profile/tankitem.cpp +++ b/qt-ui/profile/tankitem.cpp @@ -9,8 +9,8 @@ TankItem::TankItem(QObject *parent) : QGraphicsRectItem(), dataModel(0), - dive(0), - pInfo(0) + pInfoEntry(0), + pInfoNr(0) { height = 3; QColor red(PERSIANRED1); @@ -30,12 +30,19 @@ TankItem::TankItem(QObject *parent) : trimixGradient.setColorAt(1.0, red); trimix = trimixGradient; air = blue; + memset(&diveCylinderStore, 0, sizeof(diveCylinderStore)); } void TankItem::setData(DivePlotDataModel *model, struct plot_info *plotInfo, struct dive *d) { - pInfo = plotInfo; - dive = d; + free(pInfoEntry); + // the plotInfo and dive structures passed in could become invalid before we stop using them, + // so copy the data that we need + int size = plotInfo->nr * sizeof(plotInfo->entry[0]); + pInfoEntry = (struct plot_data *)malloc(size); + pInfoNr = plotInfo->nr; + memcpy(pInfoEntry, plotInfo->entry, size); + copy_cylinders(d, &diveCylinderStore, false); dataModel = model; connect(dataModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(modelDataChanged(QModelIndex, QModelIndex))); modelDataChanged(); @@ -65,7 +72,7 @@ void TankItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &b { // We don't have enougth data to calculate things, quit. - if (!dive || !dataModel || !pInfo || !pInfo->nr) + if (!dataModel || !pInfoEntry || !pInfoNr) return; // remove the old rectangles @@ -75,21 +82,21 @@ void TankItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &b rects.clear(); // walk the list and figure out which tanks go where - struct plot_data *entry = pInfo->entry; + struct plot_data *entry = pInfoEntry; int cylIdx = entry->cylinderindex; int i = -1; int startTime = 0; - struct gasmix *gas = &dive->cylinder[cylIdx].gasmix; + struct gasmix *gas = &diveCylinderStore.cylinder[cylIdx].gasmix; qreal width, left; - while (++i < pInfo->nr) { - entry = &pInfo->entry[i]; + while (++i < pInfoNr) { + entry = &pInfoEntry[i]; if (entry->cylinderindex == cylIdx) continue; width = hAxis->posAtValue(entry->sec) - hAxis->posAtValue(startTime); left = hAxis->posAtValue(startTime); createBar(left, width, gas); cylIdx = entry->cylinderindex; - gas = &dive->cylinder[cylIdx].gasmix; + gas = &diveCylinderStore.cylinder[cylIdx].gasmix; startTime = entry->sec; } width = hAxis->posAtValue(entry->sec) - hAxis->posAtValue(startTime); diff --git a/qt-ui/profile/tankitem.h b/qt-ui/profile/tankitem.h index 615a7017d..f8d4ac9f8 100644 --- a/qt-ui/profile/tankitem.h +++ b/qt-ui/profile/tankitem.h @@ -28,8 +28,9 @@ private: DivePlotDataModel *dataModel; DiveCartesianAxis *hAxis; int hDataColumn; - struct dive *dive; - struct plot_info *pInfo; + struct dive diveCylinderStore; + struct plot_data *pInfoEntry; + int pInfoNr; qreal yPos, height; QBrush air, nitrox, trimix; QList<QGraphicsRectItem *> rects; |