Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f686040

Browse files
jvanverthSkia Commit-Bot
authored andcommitted
Use fuzzier definition of zero-length segments in compute_intersection.
When working with segments in compute_intersection, we're often dividing by the length squared. If that's 0, we'll end up dividing by 0. This effectively puts a lower bound on the size of segment we can determine intersections with other than treating it like a single point. We arbitrarily choose the first endpoint as this point. Bug: oss-fuzz:20009 Change-Id: I7581922f704ff8cef77456a80159cdb8ba3b716f Reviewed-on: https://skia-review.googlesource.com/c/skia/+/282160 Auto-Submit: Jim Van Verth <[email protected]> Commit-Queue: Kevin Lubick <[email protected]> Reviewed-by: Kevin Lubick <[email protected]>
1 parent 6a5187a commit f686040

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

src/utils/SkPolyUtils.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,16 @@ static inline bool outside_interval(SkScalar numer, SkScalar denom, bool denomPo
7979
(!denomPositive && (numer > 0 || numer < denom));
8080
}
8181

82+
// special zero-length test when we're using vdotv as a denominator
83+
static inline bool zero_length(const SkPoint& v, SkScalar vdotv) {
84+
return !(SkScalarsAreFinite(v.fX, v.fY) && vdotv);
85+
}
86+
8287
// Compute the intersection 'p' between segments s0 and s1, if any.
8388
// 's' is the parametric value for the intersection along 's0' & 't' is the same for 's1'.
8489
// Returns false if there is no intersection.
90+
// If the length squared of a segment is 0, then we treat the segment as degenerate
91+
// and use only the first endpoint for tests.
8592
static bool compute_intersection(const OffsetSegment& s0, const OffsetSegment& s1,
8693
SkPoint* p, SkScalar* s, SkScalar* t) {
8794
const SkVector& v0 = s0.fV;
@@ -98,35 +105,39 @@ static bool compute_intersection(const OffsetSegment& s0, const OffsetSegment& s
98105
}
99106

100107
// Check for zero-length segments
101-
if (!SkPointPriv::CanNormalize(v0.fX, v0.fY)) {
108+
SkScalar v0dotv0 = v0.dot(v0);
109+
if (zero_length(v0, v0dotv0)) {
102110
// Both are zero-length
103-
if (!SkPointPriv::CanNormalize(v1.fX, v1.fY)) {
111+
SkScalar v1dotv1 = v1.dot(v1);
112+
if (zero_length(v1, v1dotv1)) {
104113
// Check if they're the same point
105114
if (!SkPointPriv::CanNormalize(w.fX, w.fY)) {
106115
*p = s0.fP0;
107116
*s = 0;
108117
*t = 0;
109118
return true;
110119
} else {
120+
// Intersection is indeterminate
111121
return false;
112122
}
113123
}
114124
// Otherwise project segment0's origin onto segment1
115125
tNumer = v1.dot(-w);
116-
denom = v1.dot(v1);
126+
denom = v1dotv1;
117127
if (outside_interval(tNumer, denom, true)) {
118128
return false;
119129
}
120130
sNumer = 0;
121131
} else {
122132
// Project segment1's endpoints onto segment0
123133
sNumer = v0.dot(w);
124-
denom = v0.dot(v0);
134+
denom = v0dotv0;
125135
tNumer = 0;
126136
if (outside_interval(sNumer, denom, true)) {
127137
// The first endpoint doesn't lie on segment0
128138
// If segment1 is degenerate, then there's no collision
129-
if (!SkPointPriv::CanNormalize(v1.fX, v1.fY)) {
139+
SkScalar v1dotv1 = v1.dot(v1);
140+
if (zero_length(v1, v1dotv1)) {
130141
return false;
131142
}
132143

@@ -143,7 +154,7 @@ static bool compute_intersection(const OffsetSegment& s0, const OffsetSegment& s
143154
// otherwise project segment0's endpoint onto segment1 instead
144155
sNumer = 0;
145156
tNumer = v1.dot(-w);
146-
denom = v1.dot(v1);
157+
denom = v1dotv1;
147158
}
148159
}
149160
}

0 commit comments

Comments
 (0)