← All issues

[13] SVG RenderSVGShape Null Dereference in isPointInStroke

Severity: Low | Component: WebCore SVG rendering | 389fcd9

Rated Low because the observable effect is a reliable null dereference (renderer crash) with no commit-backed evidence of memory corruption — null-page protections on modern platforms prevent escalation beyond denial of service.

In both RenderSVGShape::shapeDependentStrokeContains and LegacyRenderSVGShape::shapeDependentStrokeContains, the patch replaces the unconditional m_path-> dereference in the LocalCoordinateSpace fallback path with ensurePath().strokeContains(...), which lazily creates the path if null.

Source/WebCore/rendering/svg/RenderSVGShape.cpp

bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point, PointCoordinateSpace pointCoordinateSpace)
{
- ASSERT(m_path);
-
if (hasNonScalingStroke() && pointCoordinateSpace != LocalCoordinateSpace) {
+ ASSERT(m_path);
AffineTransform nonScalingTransform = nonScalingStrokeTransform();
Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform);
return usePath->strokeContains(nonScalingTransform.mapPoint(point), [this] (GraphicsContext& context) {
@@ ...
}
 
- return m_path->strokeContains(point, [this] (GraphicsContext& context) {
+ return ensurePath().strokeContains(point, [this] (GraphicsContext& context) {
SVGRenderSupport::applyStrokeStyleToContext(context, style(), *this);
});
}

LayoutTests/svg/dom/SVGGeometry-isPointInStroke-with-null-path.html

+<svg style="stroke: black; display: table-caption">
+ <polygon id="polygon"></polygon>
+</svg>
+<script>
+ document.getElementById("polygon").isPointInStroke();
+</script>

Missing null guard on a lazily-initialized path object before dereference in a JS-reachable SVG hit-testing API.

SVG geometry elements (<path>, <polygon>, <circle>, etc.) expose the isPointInStroke() method via the SVGGeometryElement interface, performing hit-testing against the element's stroked outline. Internally, WebKit represents the element's geometric shape via an m_path member (std::unique_ptr<Path>), which is lazily initialized during layout. ensurePath() is an accessor that creates the path on demand if it does not yet exist.

When isPointInStroke() is called from JavaScript on an SVG geometry element whose path has not been computed (e.g., an empty <polygon> with no points), m_path is null. The call reaches shapeDependentStrokeContains via isPointInStroke() with LocalCoordinateSpace, bypasses the non-scaling-stroke branch, and dereferences the null m_path pointer directly.

🔒

Explores the reachability and exploitation potential of this crash beyond simple denial of service

Subscribe to read more

🔒

Multiple variant discovery patterns identified across SVG rendering APIs and parallel code paths

Subscribe to read more