Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdbusdemarshaller.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:critical reason:data-parser
4
7
8#include <memory>
9
10#include <stdlib.h>
11
12QT_BEGIN_NAMESPACE
13
14template <typename T>
15static inline T qIterGet(DBusMessageIter *it)
16{
17 // Use a union of expected and largest type q_dbus_message_iter_get_basic
18 // will return to ensure reading the wrong basic type does not result in
19 // stack overwrite
20 union {
21 // The value to be extracted
22 T t;
23 // Largest type that q_dbus_message_iter_get_basic will return
24 // according to dbus_message_iter_get_basic API documentation
25 dbus_uint64_t maxValue;
26 // A pointer to ensure no stack overwrite in case there is a platform
27 // where sizeof(void*) > sizeof(dbus_uint64_t)
28 void* ptr;
29 } value;
30
31 // Initialize the value in case a narrower type is extracted to it.
32 // Note that the result of extracting a narrower type in place of a wider
33 // one and vice-versa will be platform-dependent.
34 value.t = T();
35
36 q_dbus_message_iter_get_basic(it, &value);
37 q_dbus_message_iter_next(it);
38 return value.t;
39}
40
44
46{
47 char *sig = q_dbus_message_iter_get_signature(&iterator);
48 QString retval = QString::fromUtf8(sig);
49 q_dbus_free(sig);
50
51 return retval;
52}
53
55{
56 return qIterGet<uchar>(&iterator);
57}
58
60{
61 return bool(qIterGet<dbus_bool_t>(&iterator));
62}
63
65{
66 return qIterGet<dbus_uint16_t>(&iterator);
67}
68
70{
71 return qIterGet<dbus_int16_t>(&iterator);
72}
73
75{
76 return qIterGet<dbus_int32_t>(&iterator);
77}
78
80{
81 return qIterGet<dbus_uint32_t>(&iterator);
82}
83
85{
86 return qIterGet<qlonglong>(&iterator);
87}
88
90{
91 return qIterGet<qulonglong>(&iterator);
92}
93
95{
96 return qIterGet<double>(&iterator);
97}
98
99inline QString QDBusDemarshaller::toStringUnchecked()
100{
101 return QString::fromUtf8(qIterGet<char *>(&iterator));
102}
103
105{
107 return toStringUnchecked();
108 else
109 return QString();
110}
111
112inline QDBusObjectPath QDBusDemarshaller::toObjectPathUnchecked()
113 {
114 return QDBusObjectPath(QString::fromUtf8(qIterGet<char *>(&iterator)));
115 }
116
118{
120 return toObjectPathUnchecked();
121 else
122 return QDBusObjectPath();
123}
124
125inline QDBusSignature QDBusDemarshaller::toSignatureUnchecked()
126 {
127 return QDBusSignature(QString::fromUtf8(qIterGet<char *>(&iterator)));
128 }
129
131{
133 return toSignatureUnchecked();
134 else
135 return QDBusSignature();
136}
137
138inline QDBusUnixFileDescriptor QDBusDemarshaller::toUnixFileDescriptor()
139{
140 QDBusUnixFileDescriptor fd;
141 fd.giveFileDescriptor(qIterGet<dbus_int32_t>(&iterator));
142 return fd;
143}
144
146{
147 QDBusDemarshaller sub(capabilities);
148 sub.message = q_dbus_message_ref(message);
149 q_dbus_message_iter_recurse(&iterator, &sub.iterator);
151
152 return QDBusVariant( sub.toVariantInternal() );
153}
154
155QDBusArgument::ElementType QDBusDemarshaller::currentType()
156{
157 switch (q_dbus_message_iter_get_arg_type(&iterator)) {
158 case DBUS_TYPE_BYTE:
159 case DBUS_TYPE_INT16:
160 case DBUS_TYPE_UINT16:
161 case DBUS_TYPE_INT32:
162 case DBUS_TYPE_UINT32:
163 case DBUS_TYPE_INT64:
164 case DBUS_TYPE_UINT64:
166 case DBUS_TYPE_DOUBLE:
167 case DBUS_TYPE_STRING:
170 return QDBusArgument::BasicType;
171
173 return QDBusArgument::VariantType;
174
175 case DBUS_TYPE_ARRAY:
176 switch (q_dbus_message_iter_get_element_type(&iterator)) {
177 case DBUS_TYPE_BYTE:
178 case DBUS_TYPE_STRING:
179 // QByteArray and QStringList
180 return QDBusArgument::BasicType;
182 return QDBusArgument::MapType;
183 default:
184 return QDBusArgument::ArrayType;
185 }
186
187 case DBUS_TYPE_STRUCT:
188 return QDBusArgument::StructureType;
190 return QDBusArgument::MapEntryType;
191
193 return capabilities & QDBusConnection::UnixFileDescriptorPassing ?
194 QDBusArgument::BasicType : QDBusArgument::UnknownType;
195
197 return QDBusArgument::UnknownType;
198
199// default:
200// qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'",
201// q_dbus_message_iter_get_arg_type(&iterator),
202// q_dbus_message_iter_get_arg_type(&iterator));
203 }
204 return QDBusArgument::UnknownType;
205}
206
207// This function performs no size, nesting-depth, or type-validity checks of
208// its own (note the unbounded recursion into toVariant() for DBUS_TYPE_VARIANT
209// below). That is not an oversight: libdbus-1 already rejects malformed
210// messages (oversized arrays/strings/messages, excessive variant nesting,
211// unknown type bytes) before QtDBus ever sees them, in its own message-load
212// path. If libdbus-1's validation were ever bypassed or weakened, QtDBus has
213// no independent check of its own to fall back on here.
215{
216 switch (q_dbus_message_iter_get_arg_type(&iterator)) {
217 case DBUS_TYPE_BYTE:
218 return QVariant::fromValue(toByte());
219 case DBUS_TYPE_INT16:
220 return QVariant::fromValue(toShort());
221 case DBUS_TYPE_UINT16:
222 return QVariant::fromValue(toUShort());
223 case DBUS_TYPE_INT32:
224 return toInt();
225 case DBUS_TYPE_UINT32:
226 return toUInt();
227 case DBUS_TYPE_DOUBLE:
228 return toDouble();
230 return toBool();
231 case DBUS_TYPE_INT64:
232 return toLongLong();
233 case DBUS_TYPE_UINT64:
234 return toULongLong();
235 case DBUS_TYPE_STRING:
236 return toStringUnchecked();
238 return QVariant::fromValue(toObjectPathUnchecked());
240 return QVariant::fromValue(toSignatureUnchecked());
242 return QVariant::fromValue(toVariant());
243
244 case DBUS_TYPE_ARRAY:
245 switch (q_dbus_message_iter_get_element_type(&iterator)) {
246 case DBUS_TYPE_BYTE:
247 // QByteArray
248 return toByteArrayUnchecked();
249 case DBUS_TYPE_STRING:
250 return toStringListUnchecked();
252 return QVariant::fromValue(duplicate());
253
254 default:
255 return QVariant::fromValue(duplicate());
256 }
257
258 case DBUS_TYPE_STRUCT:
259 return QVariant::fromValue(duplicate());
260
262 if (capabilities & QDBusConnection::UnixFileDescriptorPassing)
263 return QVariant::fromValue(toUnixFileDescriptor());
264 Q_FALLTHROUGH();
265
266 default:
267// qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'",
268// q_dbus_message_iter_get_arg_type(&iterator),
269// q_dbus_message_iter_get_arg_type(&iterator));
270 char *ptr = nullptr;
271 ptr += q_dbus_message_iter_get_arg_type(&iterator);
273
274 // I hope you never dereference this pointer!
275 return QVariant::fromValue<void *>(ptr);
276 };
277}
278
280{
281 const int type = q_dbus_message_iter_get_arg_type(&iterator);
282 switch (type) {
283 case DBUS_TYPE_STRING: //FALLTHROUGH
284 case DBUS_TYPE_OBJECT_PATH: //FALLTHROUGH
286 return true;
287 default:
288 return false;
289 }
290}
291
292QStringList QDBusDemarshaller::toStringListUnchecked()
293{
294 QStringList list;
295
296 QDBusDemarshaller sub(capabilities);
297 q_dbus_message_iter_recurse(&iterator, &sub.iterator);
299 while (!sub.atEnd())
300 list.append(sub.toStringUnchecked());
301
302 return list;
303}
304
306{
307 if (q_dbus_message_iter_get_arg_type(&iterator) == DBUS_TYPE_ARRAY
308 && q_dbus_message_iter_get_element_type(&iterator) == DBUS_TYPE_STRING)
309 return toStringListUnchecked();
310 else
311 return QStringList();
312}
313
314QByteArray QDBusDemarshaller::toByteArrayUnchecked()
315{
316 DBusMessageIter sub;
319 int len;
320 char* data;
322 return QByteArray(data,len);
323}
324
326{
327 if (q_dbus_message_iter_get_arg_type(&iterator) == DBUS_TYPE_ARRAY
328 && q_dbus_message_iter_get_element_type(&iterator) == DBUS_TYPE_BYTE) {
329 return toByteArrayUnchecked();
330 }
331 return QByteArray();
332}
333
335{
336 // dbus_message_iter_has_next is broken if the list has one single element
337 return q_dbus_message_iter_get_arg_type(&iterator) == DBUS_TYPE_INVALID;
338}
339
344
349
354
359
361{
362 QDBusDemarshaller *d = new QDBusDemarshaller(capabilities);
363 d->parent = this;
364 d->message = q_dbus_message_ref(message);
365
366 // recurse
369 return d;
370}
371
376
381
383{
384 return endCommon();
385}
386
391
393{
394 QDBusDemarshaller *retval = parent;
395 delete this;
396 return retval;
397}
398
400{
401 std::unique_ptr<QDBusDemarshaller> d(new QDBusDemarshaller(capabilities));
402 d->iterator = iterator;
403 d->message = q_dbus_message_ref(message);
404
406 return QDBusArgumentPrivate::create(d.release());
407}
408
409QT_END_NAMESPACE
QDBusDemarshaller * beginArray()
QDBusArgument duplicate()
QDBusDemarshaller * endArray()
QDBusDemarshaller * endStructure()
QDBusDemarshaller * endMapEntry()
QDBusSignature toSignature()
QDBusUnixFileDescriptor toUnixFileDescriptor()
QDBusObjectPath toObjectPath()
QDBusDemarshaller * beginStructure()
QDBusDemarshaller * endCommon()
QDBusDemarshaller * beginMapEntry()
QDBusDemarshaller * beginCommon()
DBusMessageIter iterator
QDBusDemarshaller * endMap()
QDBusDemarshaller * beginMap()
QDBusDemarshaller * parent
QDBusArgument::ElementType currentType()
quint32 dbus_uint32_t
#define DBUS_TYPE_SIGNATURE
#define DBUS_TYPE_OBJECT_PATH
qint16 dbus_int16_t
#define DBUS_TYPE_BYTE
#define DBUS_TYPE_INT16
#define DBUS_TYPE_VARIANT
#define DBUS_TYPE_INT32
#define DBUS_TYPE_UNIX_FD
#define DBUS_TYPE_BOOLEAN
quint16 dbus_uint16_t
dbus_uint32_t dbus_bool_t
#define DBUS_TYPE_STRING
qint32 dbus_int32_t
#define DBUS_TYPE_ARRAY
#define DBUS_TYPE_INVALID
#define DBUS_TYPE_INT64
#define DBUS_TYPE_DOUBLE
#define DBUS_TYPE_UINT64
#define DBUS_TYPE_DICT_ENTRY
#define DBUS_TYPE_UINT16
#define DBUS_TYPE_STRUCT
#define DBUS_TYPE_UINT32
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return dbus_message_iter_recurse
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void dbus_message_iter_get_fixed_array
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return dbus_message_iter_next