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)
This commit is contained in:
parent
5fa5013ddf
commit
419505ab01
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user