Make qt_check_pointer more OOM-safe

First, it can never return, so we can mark it Q_NORETURN and add an
std::termianate at the end. Though if it did, we'd end up in a null-
pointer dereference crash in the caller.

Second, add Q_DECL_NOTHROW to it. It can't throw, but it terminates
execution. This also prevents both puts and fprintf from escaping via
pthread asynchronous cancellation on Linux/glibc.

Third, don't use QMessageLogger, since that allocates memory and
actually uses QString. If we really are in an OOM situation, then
QString's failed allocation would recurse back into qt_check_pointer.
We'd compound the OOM situation with a stack overflow...

Change-Id: Ia53158e207a94bf49489fffd14c81c47971f4e82
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Thiago Macieira 2017-06-14 15:06:09 -07:00
parent 2b991efc47
commit 2f8a08f31b
2 changed files with 13 additions and 6 deletions

View File

@ -3016,13 +3016,20 @@ QString QSysInfo::machineHostName()
If this macro is used outside a function, the behavior is undefined.
*/
/*
The Q_CHECK_PTR macro calls this function if an allocation check
fails.
/*!
\internal
The Q_CHECK_PTR macro calls this function if an allocation check
fails.
*/
void qt_check_pointer(const char *n, int l)
void qt_check_pointer(const char *n, int l) Q_DECL_NOTHROW
{
QMessageLogger(n, l, nullptr).fatal("Out of memory");
// make separate printing calls so that the first one may flush;
// the second one could want to allocate memory (fputs prints a
// newline and stderr auto-flushes).
fputs("Out of memory", stderr);
fprintf(stderr, " in %s, line %d\n", n, l);
std::terminate();
}
/*

View File

@ -753,7 +753,7 @@ template <> class QStaticAssertFailure<true> {};
#define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition)
#endif
Q_CORE_EXPORT void qt_check_pointer(const char *, int);
Q_NORETURN Q_CORE_EXPORT void qt_check_pointer(const char *, int) Q_DECL_NOTHROW;
Q_CORE_EXPORT void qBadAlloc();
#ifdef QT_NO_EXCEPTIONS