From 621ab8ab59901cc3f9bd98be709929c9eac997a8 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Tue, 4 Sep 2018 11:08:06 +0200 Subject: [PATCH 1/5] bmp image handler: check for out of range image size Make the decoder fail early to avoid spending time and memory on attempting to decode a corrupt image file. Change-Id: I874e04f3b43122d73f8e58c7a5bcc4a741b68264 Reviewed-by: Lars Knoll --- src/gui/image/qbmphandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 587f375ce7..5dff4ab0ac 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -188,6 +188,8 @@ static bool read_dib_infoheader(QDataStream &s, BMP_INFOHDR &bi) if (!(comp == BMP_RGB || (nbits == 4 && comp == BMP_RLE4) || (nbits == 8 && comp == BMP_RLE8) || ((nbits == 16 || nbits == 32) && comp == BMP_BITFIELDS))) return false; // weird compression type + if (bi.biWidth < 0 || quint64(bi.biWidth) * qAbs(bi.biHeight) > 16384 * 16384) + return false; return true; } From e04b85b026f59120e69a4acb3f3e4469abccc325 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 10 Sep 2018 10:51:33 +0200 Subject: [PATCH 2/5] Doc: improve Mandelbrot example Change-Id: Iac6c3e681f3d5b195d08513ac5fe4b661c3d0f59 Reviewed-by: Andy Nichols --- examples/corelib/threads/doc/src/mandelbrot.qdoc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/corelib/threads/doc/src/mandelbrot.qdoc b/examples/corelib/threads/doc/src/mandelbrot.qdoc index dd0e4e5ef2..274874632e 100644 --- a/examples/corelib/threads/doc/src/mandelbrot.qdoc +++ b/examples/corelib/threads/doc/src/mandelbrot.qdoc @@ -39,7 +39,7 @@ The heavy computation here is the Mandelbrot set, probably the world's most famous fractal. These days, while sophisticated - programs such as \l{http://xaos.sourceforge.net/}{XaoS} that provide real-time zooming in the + programs such as \l{http://matek.hu/xaos/doku.php}{XaoS} that provide real-time zooming in the Mandelbrot set, the standard Mandelbrot algorithm is just slow enough for our purposes. @@ -201,7 +201,7 @@ \snippet threads/mandelbrot/renderthread.cpp 9 Once we're done with all the iterations, we call - QWaitCondition::wait() to put the thread to sleep by calling, + QWaitCondition::wait() to put the thread to sleep, unless \c restart is \c true. There's no use in keeping a worker thread looping indefinitely while there's nothing to do. @@ -232,7 +232,7 @@ \snippet threads/mandelbrot/mandelbrotwidget.cpp 0 - The implementation starts with a few contants that we'll need + The implementation starts with a few constants that we'll need later on. \snippet threads/mandelbrot/mandelbrotwidget.cpp 1 @@ -256,15 +256,15 @@ slot later on. Qt knows how to take of copy of many C++ and Qt types, but QImage isn't one of them. We must therefore call the template function qRegisterMetaType() before we can use QImage - as parameter in queued connections. + as a parameter in queued connections. \snippet threads/mandelbrot/mandelbrotwidget.cpp 2 \snippet threads/mandelbrot/mandelbrotwidget.cpp 3 \snippet threads/mandelbrot/mandelbrotwidget.cpp 4 In \l{QWidget::paintEvent()}{paintEvent()}, we start by filling - the background with black. If we have nothing yet to paint (\c - pixmap is null), we print a message on the widget asking the user + the background with black. If we have nothing to paint yet (\c + pixmap is null), we display a message on the widget asking the user to be patient and return from the function immediately. \snippet threads/mandelbrot/mandelbrotwidget.cpp 5 @@ -293,7 +293,7 @@ Notice that we rely on \c resizeEvent() being automatically called by Qt when the widget is shown the first time to generate - the image the very first time. + the initial image. \snippet threads/mandelbrot/mandelbrotwidget.cpp 11 @@ -307,7 +307,7 @@ control the zoom level. QWheelEvent::delta() returns the angle of the wheel mouse movement, in eights of a degree. For most mice, one wheel step corresponds to 15 degrees. We find out how many - mouse steps we have and determine the zoom factor in consequence. + mouse steps we have and determine the resulting zoom factor. For example, if we have two wheel steps in the positive direction (i.e., +30 degrees), the zoom factor becomes \c ZoomInFactor to the second power, i.e. 0.8 * 0.8 = 0.64. From bff307ab93bd6963f84e08e8050efa6a838dba6e Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 21 Aug 2018 14:58:43 +0200 Subject: [PATCH 3/5] Fix XCB on endian mismatched client and server with SHM off If SHM is disabled, that code path already does its own bswaping. Change-Id: I6c17f6c5c5502c8f89098d38d931b6b8f50b2640 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 9966e06c7b..c9dde35558 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -412,6 +412,8 @@ public: bool imageNeedsEndianSwap() const { + if (!hasShm()) + return false; // The non-Shm path does its own swapping #if Q_BYTE_ORDER == Q_BIG_ENDIAN return m_setup->image_byte_order != XCB_IMAGE_ORDER_MSB_FIRST; #else From 45c1473847ad65c4d43f9a605a86439867442883 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 13 Sep 2018 01:59:26 +0200 Subject: [PATCH 4/5] Detect when we are at the sentence boundary On Samsung devices this would cause it to always to captalize each word even if it was not a new sentence. Therefore we use QTextBoundaryFinder to determine if it is a new sentence or not. Task-number: QTBUG-69398 Task-number: QTBUG-66531 Change-Id: I24bf36f09a2570acfefd4343551cb1720ddc6279 Reviewed-by: BogDan Vatra Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../platforms/android/qandroidinputcontext.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index f548a1fa96..c46a435db1 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -58,6 +58,7 @@ #include #include +#include #include @@ -892,8 +893,19 @@ jint QAndroidInputContext::getCursorCapsMode(jint /*reqModes*/) return res; const uint qtInputMethodHints = query->value(Qt::ImHints).toUInt(); + const int localPos = query->value(Qt::ImCursorPosition).toInt(); - if (!(qtInputMethodHints & Qt::ImhLowercaseOnly) && !(qtInputMethodHints & Qt::ImhNoAutoUppercase)) + bool atWordBoundary = (localPos == 0); + if (!atWordBoundary) { + QString surroundingText = query->value(Qt::ImSurroundingText).toString(); + surroundingText.truncate(localPos); + // Add a character to see if it is at the end of the sentence or not + QTextBoundaryFinder finder(QTextBoundaryFinder::Sentence, surroundingText + QLatin1Char('A')); + finder.setPosition(localPos); + if (finder.isAtBoundary()) + atWordBoundary = finder.isAtBoundary(); + } + if (atWordBoundary && !(qtInputMethodHints & Qt::ImhLowercaseOnly) && !(qtInputMethodHints & Qt::ImhNoAutoUppercase)) res |= CAP_MODE_SENTENCES; if (qtInputMethodHints & Qt::ImhUppercaseOnly) From 49efea26a5fae8c2275999c36c7c8d24cf4125de Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 12 Sep 2018 10:04:39 +0200 Subject: [PATCH 5/5] sqlite: Fix QSqlError handling when opening/closing database Both sqlite3_open_v2 and sqlite3_close are documented to return an error code: https://www.sqlite.org/c3ref/open.html https://sqlite.org/c3ref/close.html However, those were ignored (other than checking whether the operation succeeded), causing QSqlError::nativeErrorCode() to always be "-1" when there was an error while opening/closing the database. Additionally, the error string needs to be read (via sqlite3_errmsg16) in qMakeError *before* d->access is set to 0, or the databaseText() will always be "out of memory" no matter what error actually happened. Task-number: QTBUG-70506 Change-Id: I75cbf178c9711442e640afd26c4502214d20c598 Reviewed-by: Andy Shaw Reviewed-by: Simon Hausmann Reviewed-by: Edward Welbourne --- src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp | 19 ++++++++++++------- .../kernel/qsqldatabase/tst_qsqldatabase.cpp | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp index 2a770d0245..491d903137 100644 --- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp +++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp @@ -109,7 +109,7 @@ static QVariant::Type qGetColumnType(const QString &tpName) } static QSqlError qMakeError(sqlite3 *access, const QString &descr, QSqlError::ErrorType type, - int errorCode = -1) + int errorCode) { return QSqlError(descr, QString(reinterpret_cast(sqlite3_errmsg16(access))), @@ -803,7 +803,9 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c openMode |= SQLITE_OPEN_NOMUTEX; - if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, NULL) == SQLITE_OK) { + const int res = sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, NULL); + + if (res == SQLITE_OK) { sqlite3_busy_timeout(d->access, timeOut); setOpen(true); setOpenError(false); @@ -816,14 +818,15 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c #endif return true; } else { + setLastError(qMakeError(d->access, tr("Error opening database"), + QSqlError::ConnectionError, res)); + setOpenError(true); + if (d->access) { sqlite3_close(d->access); d->access = 0; } - setLastError(qMakeError(d->access, tr("Error opening database"), - QSqlError::ConnectionError)); - setOpenError(true); return false; } } @@ -840,8 +843,10 @@ void QSQLiteDriver::close() sqlite3_update_hook(d->access, NULL, NULL); } - if (sqlite3_close(d->access) != SQLITE_OK) - setLastError(qMakeError(d->access, tr("Error closing database"), QSqlError::ConnectionError)); + const int res = sqlite3_close(d->access); + + if (res != SQLITE_OK) + setLastError(qMakeError(d->access, tr("Error closing database"), QSqlError::ConnectionError, res)); d->access = 0; setOpen(false); setOpenError(false); diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp index 1f055e9c33..8cf43e243b 100644 --- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp @@ -197,6 +197,8 @@ private slots: void sqlite_enableRegexp_data() { generic_data("QSQLITE"); } void sqlite_enableRegexp(); + void sqlite_openError(); + private: void createTestTables(QSqlDatabase db); void dropTestTables(QSqlDatabase db); @@ -2332,6 +2334,22 @@ void tst_QSqlDatabase::sqlite_enableRegexp() QFAIL_SQL(q, next()); } +void tst_QSqlDatabase::sqlite_openError() +{ + // see QTBUG-70506 + if (!QSqlDatabase::drivers().contains("QSQLITE")) + QSKIP("Database driver QSQLITE not available"); + + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "sqlite_openError"); + db.setDatabaseName("/doesnotexist/foo.sqlite"); + QVERIFY(db.isValid()); + + QVERIFY(!db.open()); + QSqlError error = db.lastError(); + QCOMPARE(error.nativeErrorCode(), "14"); // SQLITE_CANTOPEN + QCOMPARE(error.databaseText(), "unable to open database file"); +} + void tst_QSqlDatabase::cloneDatabase() { QFETCH(QString, dbName);