From 3f57b13504ec30f19ec617feac42f1f69736967b Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Wed, 26 Nov 2014 12:16:57 +0100 Subject: [PATCH] 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. --- src/apps/activitymonitor/ActivityView.cpp | 39 +++++++++++++++-------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/apps/activitymonitor/ActivityView.cpp b/src/apps/activitymonitor/ActivityView.cpp index f10bd84dc8..cd3eea4ce5 100644 --- a/src/apps/activitymonitor/ActivityView.cpp +++ b/src/apps/activitymonitor/ActivityView.cpp @@ -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