From 985bc72f22fa3afbd6ee0b620bcfff10b82f52f8 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Mon, 24 Jun 2024 11:07:00 +0200 Subject: [PATCH] Avoid crash in font distancefield computation A very particular glyph in one particular font would hit an assert in the glyph path simplification code. It is not clear why this happens, but at least it should not crash. So instead, this patch makes the code bail out cleanly, just leaving that glyph empty (invisible). Task-number: QTBUG-124310 Change-Id: Id3b9c0b03fb82800f029fc718000ee6ca81408f7 Pick-to: 6.7 6.5 6.2 5.15 Reviewed-by: Eskil Abrahamsen Blomfeldt (cherry picked from commit b6f962c87f5084eaf962bfb033b1398f80475120) Reviewed-by: Qt Cherry-pick Bot --- src/gui/painting/qpathsimplifier.cpp | 18 +++++++++++++----- src/gui/text/qdistancefield.cpp | 5 +++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/gui/painting/qpathsimplifier.cpp b/src/gui/painting/qpathsimplifier.cpp index 969308f0bbb..f784a643045 100644 --- a/src/gui/painting/qpathsimplifier.cpp +++ b/src/gui/painting/qpathsimplifier.cpp @@ -312,7 +312,7 @@ private: void initElements(const QVectorPath &path, const QTransform &matrix); void removeIntersections(); - void connectElements(); + bool connectElements(); void fillIndices(); BVHNode *buildTree(Element **elements, int elementCount); bool intersectNodes(QDataBuffer &elements, BVHNode *elementNode, BVHNode *treeNode); @@ -461,11 +461,17 @@ PathSimplifier::PathSimplifier(const QVectorPath &path, QDataBuffer &ver { m_points->reset(); m_indices->reset(); + bool ok = true; initElements(path, matrix); if (!m_elements.isEmpty()) { removeIntersections(); - connectElements(); - fillIndices(); + ok = connectElements(); + if (ok) + fillIndices(); + } + if (!ok) { + m_points->reset(); + m_indices->reset(); } } @@ -650,7 +656,7 @@ void PathSimplifier::removeIntersections() m_bvh.free(); // The bounding volume hierarchy is not needed anymore. } -void PathSimplifier::connectElements() +bool PathSimplifier::connectElements() { Q_ASSERT(!m_elements.isEmpty()); QDataBuffer events(m_elements.size() * 2); @@ -830,7 +836,8 @@ void PathSimplifier::connectElements() } if (!orderedElements.isEmpty()) { - Q_ASSERT((orderedElements.size() & 1) == 0); + if (orderedElements.size() & 1) // Unexpected path structure + return false; int i = 0; Element *firstElement = orderedElements.at(0); if (m_points->at(firstElement->indices[0]) != eventPoint) { @@ -856,6 +863,7 @@ void PathSimplifier::connectElements() Q_ASSERT((element->next == nullptr) == (element->previous == nullptr)); } #endif + return true; } void PathSimplifier::fillIndices() diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp index 33d3589a3ed..ecfa8b263cb 100644 --- a/src/gui/text/qdistancefield.cpp +++ b/src/gui/text/qdistancefield.cpp @@ -474,6 +474,11 @@ static void makeDistanceField(QDistanceFieldData *data, const QPainterPath &path QDataBuffer pathIndices(0); QDataBuffer pathVertices(0); qSimplifyPath(path, pathVertices, pathIndices, transform); + if (pathVertices.isEmpty()) { + qCWarning(lcDistanceField) << "Unexpected glyph path structure, bailing out"; + memset(data->data, 0, data->nbytes); + return; + } const qint32 interiorColor = -0x7f80; // 8:8 signed format, -127.5 const qint32 exteriorColor = 0x7f80; // 8:8 signed format, 127.5