From 78821cd51c69757a7b4e711c495e702adf97d682 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Fri, 29 Apr 2011 16:46:33 +0200 Subject: Revert symbol addition in b033bb9 Because it breaks forward compatibility. We will use the original fix in 4.8. In 4.7 we just make sure it doesn't crash in QTextBlock::next(). Reviewed-by: Thiago Macieira --- src/gui/text/qtextobject.cpp | 7 +------ src/gui/text/qtextobject.h | 2 +- src/s60installs/eabi/QtGuiu.def | 1 - tests/auto/qtextblock/tst_qtextblock.cpp | 12 ------------ 4 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index a403cc5..2a93f67 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -891,11 +891,6 @@ QTextBlockUserData::~QTextBlockUserData() Returns true if this text block is valid; otherwise returns false. */ -bool QTextBlock::isValid() const -{ - return p != 0 && p->blockMap().isValid(n); -} - /*! \fn QTextBlock &QTextBlock::operator=(const QTextBlock &other) @@ -1493,7 +1488,7 @@ QTextBlock::iterator QTextBlock::end() const */ QTextBlock QTextBlock::next() const { - if (!isValid()) + if (!isValid() || !p->blockMap().isValid(n)) return QTextBlock(); return QTextBlock(p, p->blockMap().next(n)); diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index 73aed79..d5c1e8d 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -204,7 +204,7 @@ public: inline QTextBlock(const QTextBlock &o) : p(o.p), n(o.n) {} inline QTextBlock &operator=(const QTextBlock &o) { p = o.p; n = o.n; return *this; } - bool isValid() const; + inline bool isValid() const { return p != 0 && n != 0; } inline bool operator==(const QTextBlock &o) const { return p == o.p && n == o.n; } inline bool operator!=(const QTextBlock &o) const { return p != o.p || n != o.n; } diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 799ac43..fafa07b 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12183,5 +12183,4 @@ EXPORTS _ZN15QGraphicsSystem22releaseCachedResourcesEv @ 12182 NONAME _Z32qt_s60_setPartialScreenInputModeb @ 12183 NONAME _Z29qt_draw_decoration_for_glyphsP8QPainterPKjPK11QFixedPointiP11QFontEngineRK5QFontRK15QTextCharFormat @ 12184 NONAME - _ZNK10QTextBlock7isValidEv @ 12185 NONAME diff --git a/tests/auto/qtextblock/tst_qtextblock.cpp b/tests/auto/qtextblock/tst_qtextblock.cpp index 748d921..cec3a6a 100644 --- a/tests/auto/qtextblock/tst_qtextblock.cpp +++ b/tests/auto/qtextblock/tst_qtextblock.cpp @@ -76,7 +76,6 @@ private slots: void excludeParagraphSeparatorFragment(); void backwardsBlockIterator(); void previousBlock_qtbug18026(); - void removedBlock_qtbug18500(); private: QTextDocument *doc; @@ -182,16 +181,5 @@ void tst_QTextBlock::previousBlock_qtbug18026() QVERIFY(last.isValid()); } -void tst_QTextBlock::removedBlock_qtbug18500() -{ - cursor.insertText("line 1\nline 2\nline 3 \nline 4\n"); - cursor.setPosition(7); - QTextBlock block = cursor.block(); - cursor.setPosition(21, QTextCursor::KeepAnchor); - - cursor.removeSelectedText(); - QVERIFY(!block.isValid()); -} - QTEST_MAIN(tst_QTextBlock) #include "tst_qtextblock.moc" -- cgit v0.12 From 6db0153cd7e35e4a919a76ae2aadbf2d2510bfb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 2 May 2011 12:39:45 +0200 Subject: Fixes crash in QWidget::effectiveWinId. Widgets are left in a transitional (and incosistent) state while being re-parented, which caused QWidget::effectiveWinId() to crash in certain circumstances. See patch for more details. Auto test included. Reviewed-by: ogoffart --- src/gui/kernel/qwidget.cpp | 20 ++++++++++++++++++++ src/gui/kernel/qwidget_p.h | 1 + tests/auto/qwidget/tst_qwidget.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index ac35d42..fcb098f 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -292,6 +292,7 @@ QWidgetPrivate::QWidgetPrivate(int version) #ifndef QT_NO_IM , inheritsInputMethodHints(0) #endif + , inSetParent(0) #if defined(Q_WS_X11) , picture(0) #elif defined(Q_WS_WIN) @@ -2563,6 +2564,22 @@ WId QWidget::effectiveWinId() const if (id || !testAttribute(Qt::WA_WState_Created)) return id; QWidget *realParent = nativeParentWidget(); + if (!realParent && d_func()->inSetParent) { + // In transitional state. This is really just a workaround. The real problem + // is that QWidgetPrivate::setParent_sys (platform specific code) first sets + // the window id to 0 (setWinId(0)) before it sets the Qt::WA_WState_Created + // attribute to false. The correct way is to do it the other way around, and + // in that case the Qt::WA_WState_Created logic above will kick in and + // return 0 whenever the widget is in a transitional state. However, changing + // the original logic for all platforms is far more intrusive and might + // break existing applications. + // Note: The widget can only be in a transitional state when changing its + // parent -- everything else is an internal error -- hence explicitly checking + // against 'inSetParent' rather than doing an unconditional return whenever + // 'realParent' is 0 (which may cause strange artifacts and headache later). + return 0; + } + // This widget *must* have a native parent widget. Q_ASSERT(realParent); Q_ASSERT(realParent->internalWinId()); return realParent->internalWinId(); @@ -10041,6 +10058,7 @@ void QWidget::setParent(QWidget *parent) void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) { Q_D(QWidget); + d->inSetParent = true; bool resized = testAttribute(Qt::WA_Resized); bool wasCreated = testAttribute(Qt::WA_WState_Created); QWidget *oldtlw = window(); @@ -10195,6 +10213,8 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) ancestorProxy->d_func()->embedSubWindow(this); } #endif + + d->inSetParent = false; } /*! diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 377e3a7..c9dba29 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -759,6 +759,7 @@ public: #ifndef QT_NO_IM uint inheritsInputMethodHints : 1; #endif + uint inSetParent : 1; // *************************** Platform specific ************************************ #if defined(Q_WS_X11) // <----------------------------------------------------------- X11 diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index bb8b8b4..a851d03 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -345,6 +345,7 @@ private slots: void immediateRepaintAfterInvalidateBuffer(); #endif void effectiveWinId(); + void effectiveWinId2(); void customDpi(); void customDpiProperty(); @@ -8522,6 +8523,30 @@ void tst_QWidget::effectiveWinId() QVERIFY(child.effectiveWinId()); } +void tst_QWidget::effectiveWinId2() +{ + QWidget parent; + + class MyWidget : public QWidget { + bool event(QEvent *e) + { + if (e->type() == QEvent::WinIdChange) { + // Shouldn't crash. + effectiveWinId(); + } + + return QWidget::event(e); + } + }; + + MyWidget child; + child.setParent(&parent); + parent.show(); + + child.setParent(0); + child.setParent(&parent); +} + class CustomWidget : public QWidget { public: -- cgit v0.12 From 36e01e698beb8b5703f5d68f5b2eb9494e11a571 Mon Sep 17 00:00:00 2001 From: Tero Toivola Date: Tue, 3 May 2011 14:14:40 +0200 Subject: memory leak fix If glyph is not found from glyphSet it is created dynamically and in this case not deleted. Task-number: https://projects.maemo.org/bugzilla/show_bug.cgi?id=244326 Merge-request: 1208 Reviewed-by: Jiang Jiang --- src/gui/text/qfontengine_ft.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index e89b508..9c90964 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1800,10 +1800,12 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr } else { glyphSet = &defaultGlyphSet; } + bool needsDelete = false; Glyph * g = glyphSet->getGlyph(glyph); if (!g) { face = lockFace(); g = loadGlyphMetrics(glyphSet, glyph); + needsDelete = true; } if (g) { @@ -1812,6 +1814,8 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr overall.width = g->width; overall.height = g->height; overall.xoff = g->advance; + if (needsDelete) + delete g; } else { int left = FLOOR(face->glyph->metrics.horiBearingX); int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width); -- cgit v0.12 From 004653e63b2c20f32750c54a609572329903d8be Mon Sep 17 00:00:00 2001 From: Ademar de Souza Reis Jr Date: Fri, 21 Jan 2011 08:19:00 -0600 Subject: QPainterPath: Ignore calls with NaN/Infinite parameters QPainterPath can't handle NaNs/Inf inside coordinates, but instead of safely ignoring or aborting an operation, it shows a warning and keeps going on, with undefined behavior. Sometimes leading to infinite loops, leaks or crashes (see qtwebkit example below). This is particularly bad when QPainterPath is used to render content from untrusted sources (web or user data). As an example, there's a qtwebkit bug where the browser crashes when a particular SVG is loaded: https://bugs.webkit.org/show_bug.cgi?id=51698. Please note that "untrusted sources" doesn't apply only to network sources. This behavior can probably be exploited on applications such as file-browsers with previews enabled. Task-number: QTBUG-16664 Signed-off-by: Ademar de Souza Reis Jr Merge-request: 1026 Reviewed-by: Marius Storm-Olsen Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Samuel --- src/gui/painting/qpainterpath.cpp | 66 ++++++++++++++++++++-------- tests/auto/qpainterpath/tst_qpainterpath.cpp | 46 +++++++++++++++++++ 2 files changed, 93 insertions(+), 19 deletions(-) diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 0bb2901..4744cb5 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -628,10 +628,14 @@ void QPainterPath::moveTo(const QPointF &p) #ifdef QPP_DEBUG printf("QPainterPath::moveTo() (%.2f,%.2f)\n", p.x(), p.y()); #endif + + if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(p.x()) || qt_is_nan(p.y())) - qWarning("QPainterPath::moveTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::moveTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -674,10 +678,14 @@ void QPainterPath::lineTo(const QPointF &p) #ifdef QPP_DEBUG printf("QPainterPath::lineTo() (%.2f,%.2f)\n", p.x(), p.y()); #endif + + if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(p.x()) || qt_is_nan(p.y())) - qWarning("QPainterPath::lineTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -729,11 +737,15 @@ void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF & printf("QPainterPath::cubicTo() (%.2f,%.2f), (%.2f,%.2f), (%.2f,%.2f)\n", c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); #endif + + if (!qt_is_finite(c1.x()) || !qt_is_finite(c1.y()) || !qt_is_finite(c2.x()) || !qt_is_finite(c2.y()) + || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(c1.x()) || qt_is_nan(c1.y()) || qt_is_nan(c2.x()) || qt_is_nan(c2.y()) - || qt_is_nan(e.x()) || qt_is_nan(e.y())) - qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -782,10 +794,14 @@ void QPainterPath::quadTo(const QPointF &c, const QPointF &e) printf("QPainterPath::quadTo() (%.2f,%.2f), (%.2f,%.2f)\n", c.x(), c.y(), e.x(), e.y()); #endif + + if (!qt_is_finite(c.x()) || !qt_is_finite(c.y()) || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(c.x()) || qt_is_nan(c.y()) || qt_is_nan(e.x()) || qt_is_nan(e.y())) - qWarning("QPainterPath::quadTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::quadTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -849,11 +865,15 @@ void QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal sweepLength printf("QPainterPath::arcTo() (%.2f, %.2f, %.2f, %.2f, angle=%.2f, sweep=%.2f\n", rect.x(), rect.y(), rect.width(), rect.height(), startAngle, sweepLength); #endif + + if (!qt_is_finite(rect.x()) && !qt_is_finite(rect.y()) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height()) + || !qt_is_finite(startAngle) || !qt_is_finite(sweepLength)) { #ifndef QT_NO_DEBUG - if (qt_is_nan(rect.x()) || qt_is_nan(rect.y()) || qt_is_nan(rect.width()) || qt_is_nan(rect.height()) - || qt_is_nan(startAngle) || qt_is_nan(sweepLength)) - qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN, results are undefined"); + qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN or Inf, ignoring call"); #endif + return; + } + if (rect.isNull()) return; @@ -952,10 +972,13 @@ QPointF QPainterPath::currentPosition() const */ void QPainterPath::addRect(const QRectF &r) { + if (!qt_is_finite(r.x()) || !qt_is_finite(r.y()) || !qt_is_finite(r.width()) || !qt_is_finite(r.height())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(r.x()) || qt_is_nan(r.y()) || qt_is_nan(r.width()) || qt_is_nan(r.height())) - qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN, results are undefined"); + qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN or Inf, ignoring call"); #endif + return; + } + if (r.isNull()) return; @@ -1032,11 +1055,14 @@ void QPainterPath::addPolygon(const QPolygonF &polygon) */ void QPainterPath::addEllipse(const QRectF &boundingRect) { + if (!qt_is_finite(boundingRect.x()) || !qt_is_finite(boundingRect.y()) + || !qt_is_finite(boundingRect.width()) || !qt_is_finite(boundingRect.height())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(boundingRect.x()) || qt_is_nan(boundingRect.y()) - || qt_is_nan(boundingRect.width()) || qt_is_nan(boundingRect.height())) - qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN, results are undefined"); + qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN or Inf, ignoring call"); #endif + return; + } + if (boundingRect.isNull()) return; @@ -2358,10 +2384,12 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p) s >> x; s >> y; Q_ASSERT(type >= 0 && type <= 3); + if (!qt_is_finite(x) || !qt_is_finite(y)) { #ifndef QT_NO_DEBUG - if (qt_is_nan(x) || qt_is_nan(y)) - qWarning("QDataStream::operator>>: Adding a NaN element to path, results are undefined"); + qWarning("QDataStream::operator>>: NaN or Inf element found in path, skipping it"); #endif + continue; + } QPainterPath::Element elm = { x, y, QPainterPath::ElementType(type) }; p.d_func()->elements.append(elm); } diff --git a/tests/auto/qpainterpath/tst_qpainterpath.cpp b/tests/auto/qpainterpath/tst_qpainterpath.cpp index bc3b5d9..e9f09ea 100644 --- a/tests/auto/qpainterpath/tst_qpainterpath.cpp +++ b/tests/auto/qpainterpath/tst_qpainterpath.cpp @@ -101,6 +101,8 @@ private slots: void testToFillPolygons(); + void testNaNandInfinites(); + void closing(); void operators_data(); @@ -1159,6 +1161,50 @@ void tst_QPainterPath::testToFillPolygons() QCOMPARE(polygons.first().count(QPointF(70, 50)), 0); } +void tst_QPainterPath::testNaNandInfinites() +{ + QPainterPath path1; + QPainterPath path2 = path1; + + QPointF p1 = QPointF(qSNaN(), 1); + QPointF p2 = QPointF(qQNaN(), 1); + QPointF p3 = QPointF(qQNaN(), 1); + QPointF pInf = QPointF(qInf(), 1); + + // all these operations with NaN/Inf should be ignored + // can't test operator>> reliably, as we can't create a path with NaN to << later + + path1.moveTo(p1); + path1.moveTo(qSNaN(), qQNaN()); + path1.moveTo(pInf); + + path1.lineTo(p1); + path1.lineTo(qSNaN(), qQNaN()); + path1.lineTo(pInf); + + path1.cubicTo(p1, p2, p3); + path1.cubicTo(p1, QPointF(1, 1), QPointF(2, 2)); + path1.cubicTo(pInf, QPointF(10, 10), QPointF(5, 1)); + + path1.quadTo(p1, p2); + path1.quadTo(QPointF(1, 1), p3); + path1.quadTo(QPointF(1, 1), pInf); + + path1.arcTo(QRectF(p1, p2), 5, 5); + path1.arcTo(QRectF(pInf, QPointF(1, 1)), 5, 5); + + path1.addRect(QRectF(p1, p2)); + path1.addRect(QRectF(pInf, QPointF(1, 1))); + + path1.addEllipse(QRectF(p1, p2)); + path1.addEllipse(QRectF(pInf, QPointF(1, 1))); + + QCOMPARE(path1, path2); + + path1.lineTo(QPointF(1, 1)); + QVERIFY(path1 != path2); +} + void tst_QPainterPath::connectPathDuplicatePoint() { QPainterPath a; -- cgit v0.12 From 66aafe42f9076c0d70037ee8fad0e382828ed7bb Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Wed, 4 May 2011 10:36:05 +0200 Subject: Fix ordinal number conflict Caused by previous merge conflict. Should have made it sequential. Reviewed-by: TrustMe --- src/s60installs/eabi/QtGuiu.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 1914e1f..318b394 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12183,5 +12183,5 @@ EXPORTS _ZN15QGraphicsSystem22releaseCachedResourcesEv @ 12182 NONAME _Z32qt_s60_setPartialScreenInputModeb @ 12183 NONAME _Z29qt_draw_decoration_for_glyphsP8QPainterPKjPK11QFixedPointiP11QFontEngineRK5QFontRK15QTextCharFormat @ 12184 NONAME - _ZNK14QVolatileImage14paintingActiveEv @ 12186 NONAME + _ZNK14QVolatileImage14paintingActiveEv @ 12185 NONAME -- cgit v0.12