QCryptographicHash: auto-calculate MaxHashLength
Add Algorithm::NumAlgorithms and use it to iterate over all statically-available algorithms, querying their hashLengthInternal(). This avoids having to statically_assert(<= MaxHashLength) everywhere, and auto-adjusts the buffer size in SHA1_ONLY builds. Yes, the extra case labels for NumAlgorithms are a nuisance, but at least the compiler will remind us when we forget, unlike a missing static_cast(<= MaxHashLength) that might easily be forgotten. Adjust the test (which iterates over the QMetaEnum for QCryptographicHash::Algorithm, so finds NumAlgorithms and tries to pass it to the hash() function which responds with a Q_UNREACHABLE(). Only test hashLength() == 0 for that enum value. Pick-to: 6.5 Change-Id: I70155d2460464f0b2094e136eb6bea185effc9d5 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
10e9687159
commit
0411d98192
@ -143,15 +143,11 @@ public:
|
|||||||
{ return QByteArrayView{m_data.data(), size()}; }
|
{ return QByteArrayView{m_data.data(), size()}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr qsizetype MaxHashLength = 64;
|
|
||||||
|
|
||||||
static constexpr int hashLengthInternal(QCryptographicHash::Algorithm method) noexcept
|
static constexpr int hashLengthInternal(QCryptographicHash::Algorithm method) noexcept
|
||||||
{
|
{
|
||||||
switch (method) {
|
switch (method) {
|
||||||
#define CASE(Enum, Size) \
|
#define CASE(Enum, Size) \
|
||||||
case QCryptographicHash:: Enum : \
|
case QCryptographicHash:: Enum : \
|
||||||
/* if this triggers, then increase MaxHashLength accordingly */ \
|
|
||||||
static_assert(MaxHashLength >= qsizetype(Size) ); \
|
|
||||||
return Size \
|
return Size \
|
||||||
/*end*/
|
/*end*/
|
||||||
CASE(Sha1, 20);
|
CASE(Sha1, 20);
|
||||||
@ -172,35 +168,42 @@ static constexpr int hashLengthInternal(QCryptographicHash::Algorithm method) no
|
|||||||
CASE(Blake2s_128, 128 / 8);
|
CASE(Blake2s_128, 128 / 8);
|
||||||
case QCryptographicHash::Blake2b_160:
|
case QCryptographicHash::Blake2b_160:
|
||||||
case QCryptographicHash::Blake2s_160:
|
case QCryptographicHash::Blake2s_160:
|
||||||
static_assert(160 / 8 <= MaxHashLength);
|
|
||||||
return 160 / 8;
|
return 160 / 8;
|
||||||
case QCryptographicHash::RealSha3_224:
|
case QCryptographicHash::RealSha3_224:
|
||||||
case QCryptographicHash::Keccak_224:
|
case QCryptographicHash::Keccak_224:
|
||||||
case QCryptographicHash::Blake2s_224:
|
case QCryptographicHash::Blake2s_224:
|
||||||
static_assert(224 / 8 <= MaxHashLength);
|
|
||||||
return 224 / 8;
|
return 224 / 8;
|
||||||
case QCryptographicHash::RealSha3_256:
|
case QCryptographicHash::RealSha3_256:
|
||||||
case QCryptographicHash::Keccak_256:
|
case QCryptographicHash::Keccak_256:
|
||||||
case QCryptographicHash::Blake2b_256:
|
case QCryptographicHash::Blake2b_256:
|
||||||
case QCryptographicHash::Blake2s_256:
|
case QCryptographicHash::Blake2s_256:
|
||||||
static_assert(256 / 8 <= MaxHashLength);
|
|
||||||
return 256 / 8;
|
return 256 / 8;
|
||||||
case QCryptographicHash::RealSha3_384:
|
case QCryptographicHash::RealSha3_384:
|
||||||
case QCryptographicHash::Keccak_384:
|
case QCryptographicHash::Keccak_384:
|
||||||
case QCryptographicHash::Blake2b_384:
|
case QCryptographicHash::Blake2b_384:
|
||||||
static_assert(384 / 8 <= MaxHashLength);
|
|
||||||
return 384 / 8;
|
return 384 / 8;
|
||||||
case QCryptographicHash::RealSha3_512:
|
case QCryptographicHash::RealSha3_512:
|
||||||
case QCryptographicHash::Keccak_512:
|
case QCryptographicHash::Keccak_512:
|
||||||
case QCryptographicHash::Blake2b_512:
|
case QCryptographicHash::Blake2b_512:
|
||||||
static_assert(512 / 8 <= MaxHashLength);
|
|
||||||
return 512 / 8;
|
return 512 / 8;
|
||||||
#endif
|
#endif
|
||||||
#undef CASE
|
#undef CASE
|
||||||
|
case QCryptographicHash::NumAlgorithms: ;
|
||||||
|
// fall through
|
||||||
|
// Q_UNREACHABLE() would be BiC here, as hashLength(~~invalid~~) worked in 6.4
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr int maxHashLength()
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
using A = QCryptographicHash::Algorithm;
|
||||||
|
for (int i = 0; i < A::NumAlgorithms; ++i)
|
||||||
|
result = std::max(result, hashLengthInternal(A(i)));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USING_OPENSSL30
|
#ifdef USING_OPENSSL30
|
||||||
static constexpr const char * methodToName(QCryptographicHash::Algorithm method) noexcept
|
static constexpr const char * methodToName(QCryptographicHash::Algorithm method) noexcept
|
||||||
{
|
{
|
||||||
@ -298,7 +301,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
// protects result in finalize()
|
// protects result in finalize()
|
||||||
QBasicMutex finalizeMutex;
|
QBasicMutex finalizeMutex;
|
||||||
QSmallByteArray<MaxHashLength> result;
|
QSmallByteArray<maxHashLength()> result;
|
||||||
|
|
||||||
const QCryptographicHash::Algorithm method;
|
const QCryptographicHash::Algorithm method;
|
||||||
};
|
};
|
||||||
@ -399,6 +402,7 @@ void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant
|
|||||||
\omitvalue RealSha3_256
|
\omitvalue RealSha3_256
|
||||||
\omitvalue RealSha3_384
|
\omitvalue RealSha3_384
|
||||||
\omitvalue RealSha3_512
|
\omitvalue RealSha3_512
|
||||||
|
\omitvalue NumAlgorithms
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -578,6 +582,8 @@ void QCryptographicHashPrivate::reset() noexcept
|
|||||||
blake2s_init(&blake2sContext, hashLengthInternal(method));
|
blake2s_init(&blake2sContext, hashLengthInternal(method));
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case QCryptographicHash::NumAlgorithms:
|
||||||
|
Q_UNREACHABLE();
|
||||||
}
|
}
|
||||||
#endif // !QT_CONFIG(opensslv30)
|
#endif // !QT_CONFIG(opensslv30)
|
||||||
}
|
}
|
||||||
@ -687,6 +693,8 @@ void QCryptographicHashPrivate::addData(QByteArrayView bytes) noexcept
|
|||||||
blake2s_update(&blake2sContext, reinterpret_cast<const uint8_t *>(data), length);
|
blake2s_update(&blake2sContext, reinterpret_cast<const uint8_t *>(data), length);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case QCryptographicHash::NumAlgorithms:
|
||||||
|
Q_UNREACHABLE();
|
||||||
}
|
}
|
||||||
#endif // !QT_CONFIG(opensslv30)
|
#endif // !QT_CONFIG(opensslv30)
|
||||||
}
|
}
|
||||||
@ -878,6 +886,8 @@ void QCryptographicHashPrivate::finalizeUnchecked() noexcept
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
case QCryptographicHash::NumAlgorithms:
|
||||||
|
Q_UNREACHABLE();
|
||||||
}
|
}
|
||||||
#endif // !QT_CONFIG(opensslv30)
|
#endif // !QT_CONFIG(opensslv30)
|
||||||
}
|
}
|
||||||
@ -981,6 +991,12 @@ static int qt_hash_block_size(QCryptographicHash::Algorithm method)
|
|||||||
case QCryptographicHash::Blake2s_256:
|
case QCryptographicHash::Blake2s_256:
|
||||||
return BLAKE2S_BLOCKBYTES;
|
return BLAKE2S_BLOCKBYTES;
|
||||||
#endif // QT_CRYPTOGRAPHICHASH_ONLY_SHA1
|
#endif // QT_CRYPTOGRAPHICHASH_ONLY_SHA1
|
||||||
|
case QCryptographicHash::NumAlgorithms:
|
||||||
|
#if !defined(Q_GCC_ONLY) || Q_CC_GCC >= 900
|
||||||
|
// GCC 8 has trouble with Q_UNREACHABLE() in constexpr functions
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ public:
|
|||||||
Blake2s_224,
|
Blake2s_224,
|
||||||
Blake2s_256,
|
Blake2s_256,
|
||||||
#endif
|
#endif
|
||||||
|
NumAlgorithms
|
||||||
};
|
};
|
||||||
Q_ENUM(Algorithm)
|
Q_ENUM(Algorithm)
|
||||||
|
|
||||||
|
@ -401,8 +401,15 @@ void tst_QCryptographicHash::hashLength()
|
|||||||
{
|
{
|
||||||
QFETCH(const QCryptographicHash::Algorithm, algorithm);
|
QFETCH(const QCryptographicHash::Algorithm, algorithm);
|
||||||
|
|
||||||
QByteArray output = QCryptographicHash::hash("test", algorithm);
|
qsizetype expectedSize;
|
||||||
QCOMPARE(QCryptographicHash::hashLength(algorithm), output.size());
|
if (algorithm == QCryptographicHash::NumAlgorithms) {
|
||||||
|
// It's UB to call ::hash() with NumAlgorithms, but hashLength() is
|
||||||
|
// fine and returns 0 for invalid values:
|
||||||
|
expectedSize = 0;
|
||||||
|
} else {
|
||||||
|
expectedSize = QCryptographicHash::hash("test", algorithm).size();
|
||||||
|
}
|
||||||
|
QCOMPARE(QCryptographicHash::hashLength(algorithm), expectedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QCryptographicHash::move()
|
void tst_QCryptographicHash::move()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user