From 9a55243e5320b470dd5b763203f53261597a7fda Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Thu, 13 Jul 2023 16:30:34 +0200 Subject: [PATCH] QUuid: handle quint128 and Id128Bytes data in the same way The QUuid(quint128) ctor was handing the incoming data differently from the QUuid(Id128Bytes) ctor. Same was valid for the return values of QUuid::toUint128() vs QUuid::toBytes(). The provided test didn't reveal it, because it was treating the same 128-bit input value as BE in one place, and as LE in another place. This patch fixes the test, and updates the implementation of QUuid(quint128) ctor and toUInt128() method to verify that the updated test passes. This commit amends 8566c2db85a6f579a1a0432d0b7621633158e04c Change-Id: I24edb8ba0c8f7fd15062ba0b2a94ad387c3e98b6 Reviewed-by: Thiago Macieira (cherry picked from commit 0393fa6bf244c1135a9ed20cba8649687da45b9b) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/plugin/quuid.h | 44 ++++++++++++------- tests/auto/corelib/plugin/quuid/tst_quuid.cpp | 18 +++++--- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h index b8bb5bd95ac..299ce76d7b4 100644 --- a/src/corelib/plugin/quuid.h +++ b/src/corelib/plugin/quuid.h @@ -246,26 +246,40 @@ inline QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order) noexcep constexpr QUuid::QUuid(quint128 uuid, QSysInfo::Endian order) noexcept : QUuid() { - if (order == QSysInfo::LittleEndian) - uuid = qbswap(uuid); - data1 = uint(uuid >> 96); - data2 = ushort(uuid >> 80); - data3 = ushort(uuid >> 64); - for (int i = 0; i < 8; ++i) - data4[i] = uchar(uuid >> (56 - i * 8)); + if (order == QSysInfo::BigEndian) { + data1 = qFromBigEndian(int(uuid)); + data2 = qFromBigEndian(ushort(uuid >> 32)); + data3 = qFromBigEndian(ushort(uuid >> 48)); + for (int i = 0; i < 8; ++i) + data4[i] = uchar(uuid >> (64 + i * 8)); + } else { + data1 = qFromLittleEndian(uint(uuid >> 96)); + data2 = qFromLittleEndian(ushort(uuid >> 80)); + data3 = qFromLittleEndian(ushort(uuid >> 64)); + for (int i = 0; i < 8; ++i) + data4[i] = uchar(uuid >> (56 - i * 8)); + } } constexpr quint128 QUuid::toUInt128(QSysInfo::Endian order) const noexcept { quint128 result = {}; - result = data1; - result <<= 32; - result |= (data2 << 16) | uint(data3); - result <<= 64; - for (int i = 0; i < 8; ++i) - result |= quint64(data4[i]) << (56 - i * 8); - if (order == QSysInfo::LittleEndian) - return qbswap(result); + if (order == QSysInfo::BigEndian) { + for (int i = 0; i < 8; ++i) + result |= quint64(data4[i]) << (i * 8); + result = result << 64; + result |= quint64(qToBigEndian(data3)) << 48; + result |= quint64(qToBigEndian(data2)) << 32; + result |= qToBigEndian(data1); + } else { + result = qToLittleEndian(data1); + result = result << 32; + result |= quint64(qToLittleEndian(data2)) << 16; + result |= quint64(qToLittleEndian(data3)); + result = result << 64; + for (int i = 0; i < 8; ++i) + result |= quint64(data4[i]) << (56 - i * 8); + } return result; } #endif diff --git a/tests/auto/corelib/plugin/quuid/tst_quuid.cpp b/tests/auto/corelib/plugin/quuid/tst_quuid.cpp index e759bdac856..b9fcf585fb1 100644 --- a/tests/auto/corelib/plugin/quuid/tst_quuid.cpp +++ b/tests/auto/corelib/plugin/quuid/tst_quuid.cpp @@ -250,15 +250,16 @@ void tst_QUuid::uint128() { #ifdef __SIZEOF_INT128__ constexpr quint128 u = quint128(Q_UINT64_C(0xfc69b59ecc344436)) << 64 - | Q_UINT64_C(0xa43cee95d128b8c5); - constexpr QUuid uuid(u); - static_assert(uuid.toUInt128() == u, "Round-trip through QUuid failed"); + | Q_UINT64_C(0xa43cee95d128b8c5); // This is LE + constexpr quint128 be = qToBigEndian(u); + constexpr QUuid uuid(be); + static_assert(uuid.toUInt128() == be, "Round-trip through QUuid failed"); QCOMPARE(uuid, uuidA); - QCOMPARE(quint64(uuid.toUInt128() >> 64), quint64(u >> 64)); - QCOMPARE(quint64(uuid.toUInt128()), quint64(u)); + QCOMPARE(quint64(uuid.toUInt128() >> 64), quint64(be >> 64)); + QCOMPARE(quint64(uuid.toUInt128()), quint64(be)); - quint128 le = qFromBigEndian(u); + quint128 le = qFromBigEndian(be); QCOMPARE(quint64(uuid.toUInt128(QSysInfo::LittleEndian) >> 64), quint64(le >> 64)); QCOMPARE(quint64(uuid.toUInt128(QSysInfo::LittleEndian)), quint64(le)); QCOMPARE(QUuid(le, QSysInfo::LittleEndian), uuidA); @@ -266,6 +267,11 @@ void tst_QUuid::uint128() QUuid::Id128Bytes bytes = { .data128 = { qToBigEndian(u) } }; QUuid uuid2(bytes); QCOMPARE(uuid2, uuid); + + // verify that toBytes() and toUInt128() provide bytewise similar result + constexpr quint128 val = uuid.toUInt128(); + bytes = uuid.toBytes(); + QVERIFY(memcmp(&val, bytes.data, sizeof(val)) == 0); #else QSKIP("This platform has no support for 128-bit integer"); #endif