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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user