123 lines
5.8 KiB
Diff
123 lines
5.8 KiB
Diff
|
From a3ed9b781cb0e1fa4ae3b1cedcd63bd394903db7 Mon Sep 17 00:00:00 2001
|
||
|
From: Egbert Eich <eich@suse.de>
|
||
|
Date: Tue, 18 Mar 2014 18:29:02 +0100
|
||
|
Subject: [PATCH] [xcb/xsettings] Add support for byte swapping
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
The XSettings protocol is not endian neutral. Instead it holds
|
||
|
information about endianness in the first byte. It uses the same
|
||
|
convention as X11/X.h does.
|
||
|
So far byte order handling was missing leading to nasty crashes
|
||
|
when byte order between clients setting and reading XSettings
|
||
|
differed. This patch fixes this.
|
||
|
Using the X11/X.h conventions seems to be an 'established standard',
|
||
|
this piece is missing from the Xsettings specifications. Therefore
|
||
|
this fix may introduce spurious regressions as other Xsettings
|
||
|
'providers' may use a different convention. To detect this and
|
||
|
to avoid crashes the fix also adds checks to avoid reading past
|
||
|
the end of the of the Xsettings data blob. If problems are
|
||
|
encountered: warn and bail.
|
||
|
|
||
|
Change-Id: If8acb23cca2478369633129af2d99e122a84cede
|
||
|
Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
|
||
|
---
|
||
|
src/plugins/platforms/xcb/qxcbxsettings.cpp | 43 +++++++++++++++++++++--------
|
||
|
1 file changed, 32 insertions(+), 11 deletions(-)
|
||
|
|
||
|
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
|
||
|
index 141a6cc..26d95e9 100644
|
||
|
--- a/src/plugins/platforms/xcb/qxcbxsettings.cpp
|
||
|
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
|
||
|
@@ -42,6 +42,7 @@
|
||
|
#include "qxcbxsettings.h"
|
||
|
|
||
|
#include <QtCore/QByteArray>
|
||
|
+#include <QtCore/QtEndian>
|
||
|
|
||
|
#include <X11/extensions/XIproto.h>
|
||
|
|
||
|
@@ -149,47 +150,67 @@ public:
|
||
|
{
|
||
|
if (xSettings.length() < 12)
|
||
|
return;
|
||
|
- // we ignore byteorder for now
|
||
|
char byteOrder = xSettings.at(1);
|
||
|
- Q_UNUSED(byteOrder);
|
||
|
- uint number_of_settings = *reinterpret_cast<const uint *>(xSettings.mid(8,4).constData());
|
||
|
+ if (byteOrder != LSBFirst && byteOrder != MSBFirst) {
|
||
|
+ qWarning("%s ByteOrder byte %d not 0 or 1", Q_FUNC_INFO , byteOrder);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+#define ADJUST_BO(b, t, x) \
|
||
|
+ ((b == LSBFirst) ? \
|
||
|
+ qFromLittleEndian<t>((const uchar *)(x)) : \
|
||
|
+ qFromBigEndian<t>((const uchar *)(x)))
|
||
|
+#define VALIDATE_LENGTH(x) \
|
||
|
+ if ((size_t)xSettings.length() < (offset + local_offset + 12 + x)) { \
|
||
|
+ qWarning("%s Length %d runs past end of data", Q_FUNC_INFO , x); \
|
||
|
+ return; \
|
||
|
+ }
|
||
|
|
||
|
+ uint number_of_settings = ADJUST_BO(byteOrder, quint32, xSettings.mid(8,4).constData());
|
||
|
const char *data = xSettings.constData() + 12;
|
||
|
size_t offset = 0;
|
||
|
for (uint i = 0; i < number_of_settings; i++) {
|
||
|
int local_offset = 0;
|
||
|
+ VALIDATE_LENGTH(2);
|
||
|
XSettingsType type = static_cast<XSettingsType>(*reinterpret_cast<const quint8 *>(data + offset));
|
||
|
local_offset += 2;
|
||
|
|
||
|
- quint16 name_len = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
|
||
|
+ VALIDATE_LENGTH(2);
|
||
|
+ quint16 name_len = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
|
||
|
local_offset += 2;
|
||
|
|
||
|
+ VALIDATE_LENGTH(name_len);
|
||
|
QByteArray name(data + offset + local_offset, name_len);
|
||
|
local_offset += round_to_nearest_multiple_of_4(name_len);
|
||
|
|
||
|
- int last_change_serial = *reinterpret_cast<const int *>(data + offset + local_offset);
|
||
|
+ VALIDATE_LENGTH(4);
|
||
|
+ int last_change_serial = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
|
||
|
Q_UNUSED(last_change_serial);
|
||
|
local_offset += 4;
|
||
|
|
||
|
QVariant value;
|
||
|
if (type == XSettingsTypeString) {
|
||
|
- int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
|
||
|
+ VALIDATE_LENGTH(4);
|
||
|
+ int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
|
||
|
local_offset+=4;
|
||
|
+ VALIDATE_LENGTH(value_length);
|
||
|
QByteArray value_string(data + offset + local_offset, value_length);
|
||
|
value.setValue(value_string);
|
||
|
local_offset += round_to_nearest_multiple_of_4(value_length);
|
||
|
} else if (type == XSettingsTypeInteger) {
|
||
|
- int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
|
||
|
+ VALIDATE_LENGTH(4);
|
||
|
+ int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
|
||
|
local_offset += 4;
|
||
|
value.setValue(value_length);
|
||
|
} else if (type == XSettingsTypeColor) {
|
||
|
- quint16 red = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
|
||
|
+ VALIDATE_LENGTH(2*4);
|
||
|
+ quint16 red = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
|
||
|
local_offset += 2;
|
||
|
- quint16 green = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
|
||
|
+ quint16 green = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
|
||
|
local_offset += 2;
|
||
|
- quint16 blue = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
|
||
|
+ quint16 blue = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
|
||
|
local_offset += 2;
|
||
|
- quint16 alpha= *reinterpret_cast<const quint16 *>(data + offset + local_offset);
|
||
|
+ quint16 alpha= ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
|
||
|
local_offset += 2;
|
||
|
QColor color_value(red,green,blue,alpha);
|
||
|
value.setValue(color_value);
|
||
|
--
|
||
|
1.8.4.5
|
||
|
|