diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2021-08-04 10:17:11 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2021-08-05 11:05:04 +0000 |
commit | 419505ab0163edd2a8dfb73b6fefb737d42f734e (patch) | |
tree | 7226cf59f06abc436d53fa9173c7049837516ebc | |
parent | 5fa5013ddfa7366a6f34579c6c8b8b3818365bb6 (diff) |
QXpmHandler: fix re-entrancy bug in xpm_color_name
The xpm_color_name() function returned a pointer to a function-static
buffer. This is infamously non-reentrant, and an actual problem,
because we explicitly allow QImage operations (incl. saving to an
.xpm) from non-GUI-threads.
Fix by using the CSS pattern (Caller-Supplied Storage; also used in
the QAnyStringView(char32_t) and QAnyStringView(QStringBuilder) ctors)
to force the caller to allocate storage in its own stack frame. As a
consequence, we re-gain re-entrancy, but the returned pointer is now
only valid until the end of the full-expression, which isn't a problem,
as all callers immediately pass the result to a consumer (asprintf() or
QByteArray).
[ChangeLog][QtGui][QImage] Fixed a race condition when concurrently
writing .xpm files.
Change-Id: I36d7173d53839a52f5cdf58324474c1b32c71f33
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit 73fabadcee71af858388fb245fccf4e96d4ead4e)
-rw-r--r-- | src/gui/image/qxpmhandler.cpp | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index f5fe6cb7ea..1bd9531e9b 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -49,6 +49,7 @@ #include <qvariant.h> #include <algorithm> +#include <array> QT_BEGIN_NAMESPACE @@ -1055,15 +1056,23 @@ bool qt_read_xpm_image_or_array(QIODevice *device, const char * const * source, return read_xpm_body(device, source, index, state, cpp, ncols, w, h, image); } -static const char* xpm_color_name(int cpp, int index) +namespace { +template <size_t N> +struct CharBuffer : std::array<char, N> +{ + CharBuffer() {} // avoid value-initializing the whole array +}; +} + +static const char* xpm_color_name(int cpp, int index, CharBuffer<5> && returnable = {}) { - static char returnable[5]; static const char code[] = ".#abcdefghijklmnopqrstuvwxyzABCD" "EFGHIJKLMNOPQRSTUVWXYZ0123456789"; // cpp is limited to 4 and index is limited to 64^cpp if (cpp > 1) { if (cpp > 2) { if (cpp > 3) { + returnable[4] = '\0'; returnable[3] = code[index % 64]; index /= 64; } else @@ -1083,7 +1092,7 @@ static const char* xpm_color_name(int cpp, int index) returnable[1] = '\0'; returnable[0] = code[index]; - return returnable; + return returnable.data(); } |