Revision control

Copy as Markdown

// Copyright (C) 2021 Ford Motor Company
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:critical reason:data-parser
#include <QtCore/qiodevice.h>
#include "qremoteobjectcontainers_p.h"
#include "qremoteobjectpacket_p.h"
QT_BEGIN_NAMESPACE
QDataStream &operator>>(QDataStream &ds, QtROSequentialContainer &p)
{
QByteArray typeName;
quint32 count;
ds >> typeName;
p.setValueType(typeName);
ds >> count;
p.reserve(count);
QVariant value{p.m_valueType, nullptr};
for (quint32 i = 0; i < count; i++) {
if (!p.m_valueType.load(ds, value.data())) {
qWarning("QSQ_: unable to load type '%s', returning an empty list.", p.m_valueTypeName.constData());
p.clear();
break;
}
p.append(value);
}
return ds;
}
QDataStream &operator<<(QDataStream &ds, const QtROSequentialContainer &p)
{
ds << p.m_valueTypeName;
auto pos = ds.device()->pos();
quint32 count = p.size();
ds << count;
for (quint32 i = 0; i < count; i++) {
if (!p.m_valueType.save(ds, p.at(i).data())) {
ds.device()->seek(pos);
ds.resetStatus();
ds << quint32(0);
qWarning("QSQ_: unable to save type '%s'.", p.m_valueTypeName.constData());
break;
}
}
return ds;
}
const char *descopedName(QMetaType type) {
auto name = QByteArray::fromRawData(type.name(), qstrlen(type.name()));
int index = name.lastIndexOf(':'); // Returns -1 if not found
return type.name() + index + 1;
}
QDataStream &operator>>(QDataStream &ds, QtROAssociativeContainer &p)
{
QByteArray keyTypeName, valueTypeName;
quint32 count;
ds >> keyTypeName;
ds >> valueTypeName;
p.setTypes(keyTypeName, valueTypeName);
ds >> count;
p.m_keys.reserve(count);
auto transferType = p.m_keyType;
if (p.m_keyType.flags().testFlag(QMetaType::IsEnumeration))
transferType = QRemoteObjectPackets::transferTypeForEnum(p.m_keyType);
QVariant key{transferType, nullptr};
QVariant value{p.m_valueType, nullptr};
for (quint32 i = 0; i < count; i++) {
if (!transferType.load(ds, key.data())) {
qWarning("QAS_: unable to load key '%s', returning an empty map.", p.m_keyTypeName.constData());
p.clear();
break;
}
if (!p.m_valueType.load(ds, value.data())) {
qWarning("QAS_: unable to load value '%s', returning an empty map.", p.m_valueTypeName.constData());
p.clear();
break;
}
if (transferType != p.m_keyType) {
bool isFlag = false;
QVariant enumKey(key);
enumKey.convert(p.m_keyType);
p.m_keys.append(enumKey);
if (auto meta = p.m_keyType.metaObject()) {
int index = meta->indexOfEnumerator(descopedName(p.m_keyType));
isFlag = meta->enumerator(index).isFlag();
}
// If multiple flag values are set, toString() returns an empty string
// Thus, for flags, we convert the integer value to a string
if (isFlag)
p.insert(key.toString(), value);
else
p.insert(enumKey.toString(), value);
} else {
p.insert(key.toString(), value);
p.m_keys.append(key);
}
}
return ds;
}
QDataStream &operator<<(QDataStream &ds, const QtROAssociativeContainer &p)
{
ds << p.m_keyTypeName;
ds << p.m_valueTypeName;
auto pos = ds.device()->pos();
quint32 count = p.size();
ds << count;
QMetaAssociation::Iterable map(&p);
QMetaAssociation::Iterable::const_iterator iter = map.begin();
auto transferType = p.m_keyType;
if (p.m_keyType.flags().testFlag(QMetaType::IsEnumeration))
transferType = QRemoteObjectPackets::transferTypeForEnum(p.m_keyType);
bool keySaved;
for (quint32 i = 0; i < count; i++) {
if (transferType != p.m_keyType) {
QVariant intKey(iter.key());
intKey.convert(transferType);
keySaved = transferType.save(ds, intKey.data());
} else {
keySaved = transferType.save(ds, iter.key().data());
}
if (!keySaved) {
ds.device()->seek(pos);
ds.resetStatus();
ds << quint32(0);
qWarning("QAS_: unable to save type '%s'.", p.m_valueTypeName.constData());
break;
}
if (!p.m_valueType.save(ds, iter.value().data())) {
ds.device()->seek(pos);
ds.resetStatus();
ds << quint32(0);
qWarning("QAS_: unable to save type '%s'.", p.m_valueTypeName.constData());
break;
}
iter++;
}
return ds;
}
QT_END_NAMESPACE