diff options
author | Olivier De Cannière <olivier.decanniere@qt.io> | 2023-07-28 16:30:45 +0200 |
---|---|---|
committer | Olivier De Cannière <olivier.decanniere@qt.io> | 2023-08-01 14:06:18 +0200 |
commit | 9df4293adf7d019b4d3ccaaa2f5d87ddfe0b041b (patch) | |
tree | 00a4263f24751568e62c816e8f1be75ce44621af /src/qml/common | |
parent | 115916f217b0dc299b8df298f5c9c30369f561f8 (diff) |
UndefinedBehavior: fix some things found with -sanitize undefined
Here are the sorts of things that were found:
- Uninitialized variables containing garbage.
- Calling member function through nullptr (where this is not actually
used inside the function because that would trigger a segfault).
- static_cast'ing double to int where the double is either +/-infinity
or is outside the range of min and max values for int.
Additionally, the uses of QJSNumberCoercion::isInteger() in the code
generator have been replaced by QJSNumberCoercion::isArrayIndex() and
the former was deprecated as it is no longer being used.
Pick-to: 6.5 6.6
Change-Id: I9318671ccbda37e5519f4fcb84a1537585c2103f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/common')
-rw-r--r-- | src/qml/common/qjsnumbercoercion.cpp | 14 | ||||
-rw-r--r-- | src/qml/common/qjsnumbercoercion.h | 36 | ||||
-rw-r--r-- | src/qml/common/qv4staticvalue_p.h | 2 |
3 files changed, 46 insertions, 6 deletions
diff --git a/src/qml/common/qjsnumbercoercion.cpp b/src/qml/common/qjsnumbercoercion.cpp index 986a3e97f2..ba76c12bb0 100644 --- a/src/qml/common/qjsnumbercoercion.cpp +++ b/src/qml/common/qjsnumbercoercion.cpp @@ -14,6 +14,20 @@ QT_BEGIN_NAMESPACE */ /*! + \fn bool QJSNumberCoercion::isInteger(double d) + \internal + \deprecated 6.7 + */ + +/*! + \fn bool QJSNumberCoercion::isArrayIndex(double d) + \internal + + Checks whether \a d contains a value that can serve as an index into an array. + For that, \a d must be a non-negative value representable as an int. + */ + +/*! \fn int QJSNumberCoercion::toInteger(double d) \internal diff --git a/src/qml/common/qjsnumbercoercion.h b/src/qml/common/qjsnumbercoercion.h index 03827f82f1..bc04794d2f 100644 --- a/src/qml/common/qjsnumbercoercion.h +++ b/src/qml/common/qjsnumbercoercion.h @@ -12,17 +12,43 @@ QT_BEGIN_NAMESPACE class QJSNumberCoercion { public: - static constexpr bool isInteger(double d) { - return equals(d, d) && equals(static_cast<int>(d), d); + +#if QT_DEPRECATED_SINCE(6, 7) + + QT_DEPRECATED_VERSION_6_7 + static constexpr bool isInteger(double d) + { + // Comparing d with itself checks for NaN and comparing d with the min and max values + // for int also covers infinities. + if (!equals(d, d) || d < std::numeric_limits<int>::min() + || d > std::numeric_limits<int>::max()) { + return false; + } + + return equals(static_cast<int>(d), d); + } + +#endif + + static constexpr bool isArrayIndex(double d) + { + if (d < 0 || !equals(d, d) || d > std::numeric_limits<int>::max()) { + return false; + } + + return equals(static_cast<int>(d), d); } static constexpr int toInteger(double d) { + // Check for NaN if (!equals(d, d)) return 0; - const int i = static_cast<int>(d); - if (equals(i, d)) - return i; + if (d >= std::numeric_limits<int>::min() && d <= std::numeric_limits<int>::max()) { + const int i = static_cast<int>(d); + if (equals(i, d)) + return i; + } return QJSNumberCoercion(d).toInteger(); } diff --git a/src/qml/common/qv4staticvalue_p.h b/src/qml/common/qv4staticvalue_p.h index e9c3554104..9a88fccc04 100644 --- a/src/qml/common/qv4staticvalue_p.h +++ b/src/qml/common/qv4staticvalue_p.h @@ -393,7 +393,7 @@ struct StaticValue } QV4_NEARLY_ALWAYS_INLINE static bool isInt32(double d) { - int i = int(d); + int i = QJSNumberCoercion::toInteger(d); return (i == d && !(d == 0 && std::signbit(d))); } |