1// Copyright (C) 2021 Ford Motor Company
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
5#include <QtCore/qiodevice.h>
6
7#include "qremoteobjectcontainers_p.h"
8#include "qremoteobjectpacket_p.h"
9
10QT_BEGIN_NAMESPACE
11
12QDataStream &operator>>(QDataStream &ds, QtROSequentialContainer &p)
13{
14 QByteArray typeName;
15 quint32 count;
16 ds >> typeName;
17 p.setValueType(typeName);
18 ds >> count;
19 p.reserve(asize: count);
20 QVariant value{p.m_valueType, nullptr};
21 for (quint32 i = 0; i < count; i++) {
22 if (!p.m_valueType.load(stream&: ds, data: value.data())) {
23 qWarning(msg: "QSQ_: unable to load type '%s', returning an empty list.", p.m_valueTypeName.constData());
24 p.clear();
25 break;
26 }
27 p.append(t: value);
28 }
29 return ds;
30}
31
32QDataStream &operator<<(QDataStream &ds, const QtROSequentialContainer &p)
33{
34 ds << p.m_valueTypeName;
35 auto pos = ds.device()->pos();
36 quint32 count = p.size();
37 ds << count;
38 for (quint32 i = 0; i < count; i++) {
39 if (!p.m_valueType.save(stream&: ds, data: p.at(i).data())) {
40 ds.device()->seek(pos);
41 ds.resetStatus();
42 ds << quint32(0);
43 qWarning(msg: "QSQ_: unable to save type '%s'.", p.m_valueTypeName.constData());
44 break;
45 }
46 }
47 return ds;
48}
49
50const char *descopedName(QMetaType type) {
51 auto name = QByteArray::fromRawData(data: type.name(), size: qstrlen(str: type.name()));
52 int index = name.lastIndexOf(ch: ':'); // Returns -1 if not found
53 return type.name() + index + 1;
54}
55
56QDataStream &operator>>(QDataStream &ds, QtROAssociativeContainer &p)
57{
58 QByteArray keyTypeName, valueTypeName;
59 quint32 count;
60 ds >> keyTypeName;
61 ds >> valueTypeName;
62 p.setTypes(keyTypeName, valueTypeName);
63 ds >> count;
64 p.m_keys.reserve(asize: count);
65 auto transferType = p.m_keyType;
66 if (p.m_keyType.flags().testFlag(flag: QMetaType::IsEnumeration))
67 transferType = QRemoteObjectPackets::transferTypeForEnum(enumType: p.m_keyType);
68 QVariant key{transferType, nullptr};
69 QVariant value{p.m_valueType, nullptr};
70 for (quint32 i = 0; i < count; i++) {
71 if (!transferType.load(stream&: ds, data: key.data())) {
72 qWarning(msg: "QAS_: unable to load key '%s', returning an empty map.", p.m_keyTypeName.constData());
73 p.clear();
74 break;
75 }
76 if (!p.m_valueType.load(stream&: ds, data: value.data())) {
77 qWarning(msg: "QAS_: unable to load value '%s', returning an empty map.", p.m_valueTypeName.constData());
78 p.clear();
79 break;
80 }
81 if (transferType != p.m_keyType) {
82 bool isFlag = false;
83 QVariant enumKey(key);
84 enumKey.convert(type: p.m_keyType);
85 p.m_keys.append(t: enumKey);
86 if (auto meta = p.m_keyType.metaObject()) {
87 int index = meta->indexOfEnumerator(name: descopedName(type: p.m_keyType));
88 isFlag = meta->enumerator(index).isFlag();
89 }
90 // If multiple flag values are set, toString() returns an empty string
91 // Thus, for flags, we convert the integer value to a string
92 if (isFlag)
93 p.insert(key: key.toString(), value);
94 else
95 p.insert(key: enumKey.toString(), value);
96 } else {
97 p.insert(key: key.toString(), value);
98 p.m_keys.append(t: key);
99 }
100 }
101 return ds;
102}
103
104QDataStream &operator<<(QDataStream &ds, const QtROAssociativeContainer &p)
105{
106 ds << p.m_keyTypeName;
107 ds << p.m_valueTypeName;
108 auto pos = ds.device()->pos();
109 quint32 count = p.size();
110 ds << count;
111 QAssociativeIterable map(&p);
112 QAssociativeIterable::const_iterator iter = map.begin();
113 auto transferType = p.m_keyType;
114 if (p.m_keyType.flags().testFlag(flag: QMetaType::IsEnumeration))
115 transferType = QRemoteObjectPackets::transferTypeForEnum(enumType: p.m_keyType);
116 bool keySaved;
117 for (quint32 i = 0; i < count; i++) {
118 if (transferType != p.m_keyType) {
119 QVariant intKey(iter.key());
120 intKey.convert(type: transferType);
121 keySaved = transferType.save(stream&: ds, data: intKey.data());
122 } else {
123 keySaved = transferType.save(stream&: ds, data: iter.key().data());
124 }
125 if (!keySaved) {
126 ds.device()->seek(pos);
127 ds.resetStatus();
128 ds << quint32(0);
129 qWarning(msg: "QAS_: unable to save type '%s'.", p.m_valueTypeName.constData());
130 break;
131 }
132 if (!p.m_valueType.save(stream&: ds, data: iter.value().data())) {
133 ds.device()->seek(pos);
134 ds.resetStatus();
135 ds << quint32(0);
136 qWarning(msg: "QAS_: unable to save type '%s'.", p.m_valueTypeName.constData());
137 break;
138 }
139 iter++;
140 }
141 return ds;
142}
143
144QT_END_NAMESPACE
145

source code of qtremoteobjects/src/remoteobjects/qremoteobjectcontainers.cpp