aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar fmalita@google.com <fmalita@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-17 16:27:34 +0000
committerGravatar fmalita@google.com <fmalita@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-17 16:27:34 +0000
commit6b18d2471fc8bc2b917eec7ceba10a6b602b9f01 (patch)
tree5f79f5d60d0bf3913e79aaea166fe7fd02d2d6c1
parent6c0e5225a0df3f91af5322216314d97ea59bb3b3 (diff)
Limit the maximum number of dash segments per path
https://crbug.com/165432 In order to avoid trivial out-of-memory exploits, cap path dashing at 1000000 segments per path. R=reed@google.com BUG= Review URL: https://codereview.appspot.com/6948063 git-svn-id: http://skia.googlecode.com/svn/trunk@6845 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--src/effects/SkDashPathEffect.cpp16
-rw-r--r--tests/DrawPathTest.cpp21
2 files changed, 37 insertions, 0 deletions
diff --git a/src/effects/SkDashPathEffect.cpp b/src/effects/SkDashPathEffect.cpp
index 10ef81b5d1..4f442fd1c5 100644
--- a/src/effects/SkDashPathEffect.cpp
+++ b/src/effects/SkDashPathEffect.cpp
@@ -164,6 +164,7 @@ bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src,
SkPathMeasure meas(src, false);
const SkScalar* intervals = fIntervals;
+ SkScalar dashCount = 0;
SpecialLineRec lineRec;
const bool specialLine = lineRec.init(src, dst, rec, meas.getLength(),
@@ -176,6 +177,21 @@ bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src,
int index = fInitialDashIndex;
SkScalar scale = SK_Scalar1;
+ // Since the path length / dash length ratio may be arbitrarily large, we can exert
+ // significant memory pressure while attempting to build the filtered path. To avoid this,
+ // we simply give up dashing beyond a certain threshold.
+ //
+ // The original bug report (http://crbug.com/165432) is based on a path yielding more than
+ // 90 million dash segments and crashing the memory allocator. A limit of 1 million
+ // segments seems reasonable: at 2 verbs per segment * 9 bytes per verb, this caps the
+ // maximum dash memory overhead at roughly 17MB per path.
+ static const SkScalar kMaxDashCount = 1000000;
+ dashCount += length * (fCount >> 1) / fIntervalLength;
+ if (dashCount > kMaxDashCount) {
+ dst->reset();
+ return false;
+ }
+
if (fScaleToFit) {
if (fIntervalLength >= length) {
scale = SkScalarDiv(length, fIntervalLength);
diff --git a/tests/DrawPathTest.cpp b/tests/DrawPathTest.cpp
index fdabd0198d..e8cfa54d36 100644
--- a/tests/DrawPathTest.cpp
+++ b/tests/DrawPathTest.cpp
@@ -241,6 +241,26 @@ static void test_infinite_dash(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, true);
}
+// http://crbug.com/165432
+// Limit extreme dash path effects to avoid exhausting the system memory.
+static void test_crbug_165432(skiatest::Reporter* reporter) {
+ SkPath path;
+ path.moveTo(0, 0);
+ path.lineTo(10000000, 0);
+
+ SkScalar intervals[] = { 0.5f, 0.5f };
+ SkDashPathEffect dash(intervals, 2, 0);
+
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setPathEffect(&dash);
+
+ SkPath filteredPath;
+ SkStrokeRec rec(paint);
+ REPORTER_ASSERT(reporter, !dash.filterPath(&filteredPath, path, &rec));
+ REPORTER_ASSERT(reporter, filteredPath.isEmpty());
+}
+
static void TestDrawPath(skiatest::Reporter* reporter) {
test_giantaa(reporter);
test_bug533(reporter);
@@ -251,6 +271,7 @@ static void TestDrawPath(skiatest::Reporter* reporter) {
test_inversepathwithclip(reporter);
// test_crbug131181(reporter);
test_infinite_dash(reporter);
+ test_crbug_165432(reporter);
}
#include "TestClassDef.h"