diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-02-20 12:37:21 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-02-26 13:03:51 +0100 |
commit | 45530ad4c5c6d3e90fe6d5a63f3bb551f37ad917 (patch) | |
tree | 54bd645720e8aa9ae3fc53ce76bbed8079e156a0 /src | |
parent | d072a505d7ff39d509b9c9e2de8722cd3549b4df (diff) | |
download | qtsvg-45530ad4c5c6d3e90fe6d5a63f3bb551f37ad917.tar.gz |
Restrict nested use nodes processed
To avoid exponential blow up, limit the number of use nodes processed
under a certain depth. This should still allow the common use of many
shallow uses, but limit anything dangerous.
Change-Id: I3af6dacb61c68350876fb03f056f02a287ea4e33
Fixes: QTBUG-82153
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/svg/qsvggraphics.cpp | 17 | ||||
-rw-r--r-- | src/svg/qsvgstyle_p.h | 2 |
2 files changed, 18 insertions, 1 deletions
diff --git a/src/svg/qsvggraphics.cpp b/src/svg/qsvggraphics.cpp index bcd2452..20a03ff 100644 --- a/src/svg/qsvggraphics.cpp +++ b/src/svg/qsvggraphics.cpp @@ -43,6 +43,7 @@ #include <qabstracttextdocumentlayout.h> #include <qdebug.h> +#include <qloggingcategory.h> #include <qpainter.h> #include <qscopedvaluerollback.h> #include <qtextcursor.h> @@ -53,6 +54,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcSvgDraw, "qt.svg.draw") + #define QT_SVG_DRAW_SHAPE(command) \ qreal oldOpacity = p->opacity(); \ QBrush oldBrush = p->brush(); \ @@ -469,15 +472,27 @@ void QSvgUse::draw(QPainter *p, QSvgExtraStates &states) if (Q_UNLIKELY(!m_link || isDescendantOf(m_link) || m_recursing)) return; + Q_ASSERT(states.nestedUseCount == 0 || states.nestedUseLevel > 0); + if (states.nestedUseLevel > 3 && states.nestedUseCount > (256 + states.nestedUseLevel * 2)) { + qCDebug(lcSvgDraw, "Too many nested use nodes at #%s!", qPrintable(m_linkId)); + return; + } + applyStyle(p, states); if (!m_start.isNull()) { p->translate(m_start); } + if (states.nestedUseLevel > 0) + ++states.nestedUseCount; { - QScopedValueRollback<bool> guard(m_recursing, true); + QScopedValueRollback<int> useLevelGuard(states.nestedUseLevel, states.nestedUseLevel + 1); + QScopedValueRollback<bool> recursingGuard(m_recursing, true); m_link->draw(p, states); } + if (states.nestedUseLevel == 0) + states.nestedUseCount = 0; + if (!m_start.isNull()) { p->translate(-m_start); } diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h index 39aa690..9d616d4 100644 --- a/src/svg/qsvgstyle_p.h +++ b/src/svg/qsvgstyle_p.h @@ -145,6 +145,8 @@ struct Q_SVG_PRIVATE_EXPORT QSvgExtraStates int fontWeight; Qt::FillRule fillRule; qreal strokeDashOffset; + int nestedUseLevel = 0; + int nestedUseCount = 0; bool vectorEffect; // true if pen is cosmetic }; |