ActivityMonitor: don't draw graph with negative width.

The computation of the graph width could overflow leading to an absurdly
high count of lines to be drawn. This would freeze with BShape trying to
realloc the array to bigger and bigger sizes as lines were added to it
(by increment of 256, but still), or trigerred a bad_alloc in
BeginLineArray which allocates them upfront after I converted the code
to use that (it is more appropriate).

Add sanity checks to avoid the overflow, now you can have hundreds of
graphs without problems (much more than I can fit on my screen anyway,
which I think is good enough).

Fixes #6841.
This commit is contained in:
Adrien Destugues
2014-11-26 12:16:57 +01:00
parent 31f5b8b5d2
commit 3f57b13504
+26 -13
View File
@@ -1356,6 +1356,10 @@ ActivityView::_DrawHistory(bool drawBackground)
resolution--;
}
// We would get a negative number of steps which isn't a good idea.
if (frame.IntegerWidth() <= 10)
return;
uint32 width = frame.IntegerWidth() - 10;
uint32 steps = width / step;
bigtime_t timeStep = RefreshInterval() * resolution;
@@ -1390,25 +1394,34 @@ ActivityView::_DrawHistory(bool drawBackground)
viewValues->Update(values, steps, fDrawResolution, now, timeStep,
RefreshInterval());
if (viewValues->Start() >= (int32)steps - 1)
continue;
uint32 x = viewValues->Start() * step;
BShape shape;
bool first = true;
for (uint32 i = viewValues->Start(); i < steps; x += step, i++) {
float y = _PositionForValue(source, values,
viewValues->ValueAt(i));
if (first) {
shape.MoveTo(BPoint(x, y));
first = false;
} else
shape.LineTo(BPoint(x, y));
}
view->SetHighColor(source->Color());
view->SetLineMode(B_BUTT_CAP, B_ROUND_JOIN);
view->MovePenTo(B_ORIGIN);
view->StrokeShape(&shape);
view->BeginLineArray(steps - viewValues->Start() - 1);
BPoint prev;
for (uint32 j = viewValues->Start(); j < steps; x += step, j++) {
float y = _PositionForValue(source, values,
viewValues->ValueAt(j));
if (first) {
first = false;
} else
view->AddLine(prev, BPoint(x, y), source->Color());
prev.Set(x, y);
}
view->EndLineArray();
}
// TODO: add marks when an app started or quit