From b389cb31e4ea0b9d6142542b990ceae1fc9b9c7c Mon Sep 17 00:00:00 2001 From: Robert Löhning Date: Thu, 26 Mar 2026 13:42:19 +0100 Subject: [PATCH] Test types of nodes before downcasting them A bad cast in QSvgMarker::drawHelper lead to an endless recursion resulting in a heap overflow. Credit to OSS-Fuzz which found this as issue 496327371. Amends 534d072fe9c060ca3d1b968a717513426c69c956 While fixing that, I found another, similar case and fixed it, too, although it didn't seem to cause a crash. Amends 29b848e9ac4e4e13c5b50116a81b1f2677196939 Change-Id: Ia57491aa329fea981307a709c5a6a750125fe2c7 Reviewed-by: Hatem ElKharashy (cherry picked from commit e488f852fa18c2afc2842a88eff8f66ad4105a45) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 8368ba6ff143bd6b9a7fdf235918285d9b1f5d2a) --- diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp index c52ad59..8ce005a 100644 --- a/src/svg/qsvgstructure.cpp +++ b/src/svg/qsvgstructure.cpp @@ -419,9 +419,10 @@ const bool isPainting = (boundingRect == nullptr); const auto markers = markersForNode(node); for (auto &i : markers) { - QSvgMarker *markNode = static_cast(node->document()->namedNode(i.markerId)); - if (!markNode) + QSvgNode *referencedNode = node->document()->namedNode(i.markerId); + if (!referencedNode || referencedNode->type() != QSvgNode::Marker) continue; + QSvgMarker *markNode = static_cast(referencedNode); p->save(); p->translate(i.x, i.y); @@ -726,8 +727,9 @@ // Chrome seems to return the mask of the mask if a mask is set on the mask if (this->hasMask()) { - QSvgMask *maskNode = static_cast(document()->namedNode(this->maskId())); - if (maskNode) { + QSvgNode *referencedNode = document()->namedNode(this->maskId()); + if (referencedNode && referencedNode->type() == QSvgNode::Mask) { + QSvgMask *maskNode = static_cast(referencedNode); QRectF boundsRect; return maskNode->createMask(p, states, localRect, &boundsRect); } diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index 947f7cd..ed73a8c 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -68,6 +68,8 @@ void duplicateStyleId(); void oss_fuzz_23731(); void oss_fuzz_24131(); + void oss_fuzz_496327371(); + void oss_fuzz_496327371_similar(); void oss_fuzz_24738(); void oss_fuzz_61586(); void oss_fuzz_42532991(); @@ -1786,6 +1788,25 @@ renderer.render(&painter); } +void tst_QSvgRenderer::oss_fuzz_496327371() +{ + // Bad-cast to QSvgMarker from QSvgLine -> Heap-buffer-overflow + QImage image(377, 233, QImage::Format_RGB32); + QPainter painter(&image); + QSvgRenderer renderer(QByteArray("")); + renderer.render(&painter); +} + +void tst_QSvgRenderer::oss_fuzz_496327371_similar() +{ + // modeled after 496327371 to test similar problem, needs UBSAN + QImage image(377, 233, QImage::Format_RGB32); + QPainter painter(&image); + QSvgRenderer renderer(QByteArray("" + "")); + renderer.render(&painter); +} + void tst_QSvgRenderer::oss_fuzz_24738() { // when configured with "-sanitize undefined", this resulted in: