[Development] SIGFPE in QQuickMenu and QBasicDrag

Benjamin TERRIER b.terrier at gmail.com
Thu Apr 6 12:49:36 CEST 2017


Hi,

I've started to work on a patch to fix QTBUG-45045
(https://bugreports.qt.io/browse/QTBUG-45045).

The main issue is that the cursor position is compared to "int(qInf())"
to check its validity. However casting infinity to int is undefined
behavior and in some cases can trigger a SIGFPE and crash the
process. For most users this generally does not happen because floating
points exceptions are masked by default for x86 and x86_64 cpus.

To fix this, the naive solution would be to replace "int(qInf())" by
"std::numeric_limits<int>::min()" as these two expressions evaluate to
the same value (when SIGFPE is not triggered), but this does not solves
the underlying issue.

It seems the issue comes from the fact that
"QPointF QGuiApplicationPrivate::lastCursorPosition" is initialized to
"QPointF(qInf(), qInf())", so when "QCursor::pos()" is called and there
is no screen and no cursor position was ever recorder, the value
"QPointF(qInf(), qInf()).toPoint()" is returned. And because of the way
"QPointF::toPoint()" is implemented, this is the same as
"QPoint(qRound(qInf()), qRound(qInf()))" and
"QPoint(int(qInf()), int(qInf()))". So in a way it makes sense to check
against "int(qInf())" later in the code, except it is still undefined
behavior.

IMHO a solution could be to change "QPointF::toPoint()" so that for each
coordinate -infinity is casted to std::numeric_limits<int>::min() and
+infinity is casted to std::numeric_limits<int>::max().

What do you think about this?

BR

Benjamin Terrier



More information about the Development mailing list