mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-26 13:26:22 +00:00
[Support/Hash functions] Change the final()
and result()
of the hashing functions to return an array of bytes
Returning `std::array<uint8_t, N>` is better ergonomics for the hashing functions usage, instead of a `StringRef`: * When returning `StringRef`, client code is "jumping through hoops" to do string manipulations instead of dealing with fixed array of bytes directly, which is more natural * Returning `std::array<uint8_t, N>` avoids the need for the hasher classes to keep a field just for the purpose of wrapping it and returning it as a `StringRef` As part of this patch also: * Introduce `TruncatedBLAKE3` which is useful for using BLAKE3 as the hasher type for `HashBuilder` with non-default hash sizes. * Make `MD5Result` inherit from `std::array<uint8_t, 16>` which improves & simplifies its API. Differential Revision: https://reviews.llvm.org/D123100
This commit is contained in:
parent
acfc785c0e
commit
330268ba34
@ -820,7 +820,8 @@ void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
|
||||
auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool {
|
||||
llvm::SHA1 Hasher;
|
||||
Hasher.update(AbbrevData);
|
||||
StringRef Key = Hasher.final();
|
||||
std::array<uint8_t, 20> Hash = Hasher.final();
|
||||
StringRef Key((const char *)Hash.data(), Hash.size());
|
||||
auto Iter = AbbrevDataCache.find(Key);
|
||||
if (Iter != AbbrevDataCache.end()) {
|
||||
UnitsAbbrevData[&Unit] = Iter->second.get();
|
||||
|
@ -71,8 +71,8 @@ struct ASTFileSignature : std::array<uint8_t, 20> {
|
||||
return Value;
|
||||
}
|
||||
|
||||
static ASTFileSignature create(StringRef Bytes) {
|
||||
return create(Bytes.bytes_begin(), Bytes.bytes_end());
|
||||
static ASTFileSignature create(std::array<uint8_t, 20> Bytes) {
|
||||
return ASTFileSignature(std::move(Bytes));
|
||||
}
|
||||
|
||||
static ASTFileSignature createDISentinel() {
|
||||
|
@ -1117,8 +1117,7 @@ std::pair<ASTFileSignature, ASTFileSignature>
|
||||
ASTWriter::createSignature(StringRef AllBytes, StringRef ASTBlockBytes) {
|
||||
llvm::SHA1 Hasher;
|
||||
Hasher.update(ASTBlockBytes);
|
||||
auto Hash = Hasher.result();
|
||||
ASTFileSignature ASTBlockHash = ASTFileSignature::create(Hash);
|
||||
ASTFileSignature ASTBlockHash = ASTFileSignature::create(Hasher.result());
|
||||
|
||||
// Add the remaining bytes (i.e. bytes before the unhashed control block that
|
||||
// are not part of the AST block).
|
||||
@ -1126,8 +1125,7 @@ ASTWriter::createSignature(StringRef AllBytes, StringRef ASTBlockBytes) {
|
||||
AllBytes.take_front(ASTBlockBytes.bytes_end() - AllBytes.bytes_begin()));
|
||||
Hasher.update(
|
||||
AllBytes.take_back(AllBytes.bytes_end() - ASTBlockBytes.bytes_end()));
|
||||
Hash = Hasher.result();
|
||||
ASTFileSignature Signature = ASTFileSignature::create(Hash);
|
||||
ASTFileSignature Signature = ASTFileSignature::create(Hasher.result());
|
||||
|
||||
return std::make_pair(ASTBlockHash, Signature);
|
||||
}
|
||||
|
@ -1202,7 +1202,7 @@ void CodeSignatureSection::writeHashes(uint8_t *buf) const {
|
||||
std::min(codeEnd - code, static_cast<ssize_t>(blockSize)));
|
||||
SHA256 hasher;
|
||||
hasher.update(block);
|
||||
StringRef hash = hasher.final();
|
||||
std::array<uint8_t, 32> hash = hasher.final();
|
||||
assert(hash.size() == hashSize);
|
||||
memcpy(hashes, hash.data(), hashSize);
|
||||
code += blockSize;
|
||||
|
@ -34,7 +34,7 @@ namespace llvm {
|
||||
template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN>
|
||||
using BLAKE3Result = std::array<uint8_t, NumBytes>;
|
||||
|
||||
/// A class that wrap the BLAKE3 algorithm.
|
||||
/// A class that wraps the BLAKE3 algorithm.
|
||||
class BLAKE3 {
|
||||
public:
|
||||
BLAKE3() { init(); }
|
||||
@ -70,6 +70,17 @@ public:
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Return the current output for the digested data since the last call to
|
||||
/// init().
|
||||
///
|
||||
/// Other hash functions distinguish between \p result() and \p final(), with
|
||||
/// \p result() allowing more calls into \p update(), but there's no
|
||||
// difference for the BLAKE3 hash function.
|
||||
template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN>
|
||||
BLAKE3Result<NumBytes> result() {
|
||||
return final<NumBytes>();
|
||||
}
|
||||
|
||||
/// Returns a BLAKE3 hash for the given data.
|
||||
template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN>
|
||||
static BLAKE3Result<NumBytes> hash(ArrayRef<uint8_t> Data) {
|
||||
@ -82,6 +93,32 @@ private:
|
||||
llvm_blake3_hasher Hasher;
|
||||
};
|
||||
|
||||
/// Like \p BLAKE3 but using a class-level template parameter for specifying the
|
||||
/// hash size of the \p final() and \p result() functions.
|
||||
///
|
||||
/// This is useful for using BLAKE3 as the hasher type for \p HashBuilder with
|
||||
/// non-default hash sizes.
|
||||
template <size_t NumBytes> class TruncatedBLAKE3 : public BLAKE3 {
|
||||
public:
|
||||
/// Finalize the hasher and put the result in \p Result.
|
||||
/// This doesn't modify the hasher itself, and it's possible to finalize again
|
||||
/// after adding more input.
|
||||
void final(BLAKE3Result<NumBytes> &Result) { return BLAKE3::final(Result); }
|
||||
|
||||
/// Finalize the hasher and return an output of any length, given in bytes.
|
||||
/// This doesn't modify the hasher itself, and it's possible to finalize again
|
||||
/// after adding more input.
|
||||
BLAKE3Result<NumBytes> final() { return BLAKE3::final<NumBytes>(); }
|
||||
|
||||
/// Return the current output for the digested data since the last call to
|
||||
/// init().
|
||||
///
|
||||
/// Other hash functions distinguish between \p result() and \p final(), with
|
||||
/// \p result() allowing more calls into \p update(), but there's no
|
||||
// difference for the BLAKE3 hash function.
|
||||
BLAKE3Result<NumBytes> result() { return BLAKE3::result<NumBytes>(); }
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -39,6 +39,9 @@ struct IsHashableData
|
||||
/// Declares the hasher member, and functions forwarding directly to the hasher.
|
||||
template <typename HasherT> class HashBuilderBase {
|
||||
public:
|
||||
template <typename HasherT_ = HasherT>
|
||||
using HashResultTy = decltype(std::declval<HasherT_ &>().final());
|
||||
|
||||
HasherT &getHasher() { return Hasher; }
|
||||
|
||||
/// Forward to `HasherT::update(ArrayRef<uint8_t>)`.
|
||||
@ -59,12 +62,12 @@ public:
|
||||
}
|
||||
|
||||
/// Forward to `HasherT::final()` if available.
|
||||
template <typename HasherT_ = HasherT> StringRef final() {
|
||||
template <typename HasherT_ = HasherT> HashResultTy<HasherT_> final() {
|
||||
return this->getHasher().final();
|
||||
}
|
||||
|
||||
/// Forward to `HasherT::result()` if available.
|
||||
template <typename HasherT_ = HasherT> StringRef result() {
|
||||
template <typename HasherT_ = HasherT> HashResultTy<HasherT_> result() {
|
||||
return this->getHasher().result();
|
||||
}
|
||||
|
||||
|
@ -40,26 +40,19 @@ template <typename T> class ArrayRef;
|
||||
|
||||
class MD5 {
|
||||
public:
|
||||
struct MD5Result {
|
||||
std::array<uint8_t, 16> Bytes;
|
||||
|
||||
operator std::array<uint8_t, 16>() const { return Bytes; }
|
||||
|
||||
const uint8_t &operator[](size_t I) const { return Bytes[I]; }
|
||||
uint8_t &operator[](size_t I) { return Bytes[I]; }
|
||||
|
||||
struct MD5Result : public std::array<uint8_t, 16> {
|
||||
SmallString<32> digest() const;
|
||||
|
||||
uint64_t low() const {
|
||||
// Our MD5 implementation returns the result in little endian, so the low
|
||||
// word is first.
|
||||
using namespace support;
|
||||
return endian::read<uint64_t, little, unaligned>(Bytes.data());
|
||||
return endian::read<uint64_t, little, unaligned>(data());
|
||||
}
|
||||
|
||||
uint64_t high() const {
|
||||
using namespace support;
|
||||
return endian::read<uint64_t, little, unaligned>(Bytes.data() + 8);
|
||||
return endian::read<uint64_t, little, unaligned>(data() + 8);
|
||||
}
|
||||
std::pair<uint64_t, uint64_t> words() const {
|
||||
using namespace support;
|
||||
@ -78,20 +71,20 @@ public:
|
||||
/// Finishes off the hash and puts the result in result.
|
||||
void final(MD5Result &Result);
|
||||
|
||||
/// Finishes off the hash, and returns a reference to the 16-byte hash data.
|
||||
StringRef final();
|
||||
/// Finishes off the hash, and returns the 16-byte hash data.
|
||||
MD5Result final();
|
||||
|
||||
/// Finishes off the hash, and returns a reference to the 16-byte hash data.
|
||||
/// Finishes off the hash, and returns the 16-byte hash data.
|
||||
/// This is suitable for getting the MD5 at any time without invalidating the
|
||||
/// internal state, so that more calls can be made into `update`.
|
||||
StringRef result();
|
||||
MD5Result result();
|
||||
|
||||
/// Translates the bytes in \p Res to a hex string that is
|
||||
/// deposited into \p Str. The result will be of length 32.
|
||||
static void stringifyResult(MD5Result &Result, SmallVectorImpl<char> &Str);
|
||||
|
||||
/// Computes the hash for a given bytes.
|
||||
static std::array<uint8_t, 16> hash(ArrayRef<uint8_t> Data);
|
||||
static MD5Result hash(ArrayRef<uint8_t> Data);
|
||||
|
||||
private:
|
||||
// Any 32-bit or wider unsigned integer data type will do.
|
||||
@ -109,15 +102,9 @@ private:
|
||||
MD5_u32plus block[16];
|
||||
} InternalState;
|
||||
|
||||
MD5Result Result;
|
||||
|
||||
const uint8_t *body(ArrayRef<uint8_t> Data);
|
||||
};
|
||||
|
||||
inline bool operator==(const MD5::MD5Result &LHS, const MD5::MD5Result &RHS) {
|
||||
return LHS.Bytes == RHS.Bytes;
|
||||
}
|
||||
|
||||
/// Helper to compute and return lower 64 bits of the given string's MD5 hash.
|
||||
inline uint64_t MD5Hash(StringRef Str) {
|
||||
using namespace support;
|
||||
|
@ -36,17 +36,17 @@ public:
|
||||
/// Digest more data.
|
||||
void update(StringRef Str);
|
||||
|
||||
/// Return a reference to the current raw 160-bits SHA1 for the digested data
|
||||
/// Return the current raw 160-bits SHA1 for the digested data
|
||||
/// since the last call to init(). This call will add data to the internal
|
||||
/// state and as such is not suited for getting an intermediate result
|
||||
/// (see result()).
|
||||
StringRef final();
|
||||
std::array<uint8_t, 20> final();
|
||||
|
||||
/// Return a reference to the current raw 160-bits SHA1 for the digested data
|
||||
/// Return the current raw 160-bits SHA1 for the digested data
|
||||
/// since the last call to init(). This is suitable for getting the SHA1 at
|
||||
/// any time without invalidating the internal state so that more calls can be
|
||||
/// made into update.
|
||||
StringRef result();
|
||||
std::array<uint8_t, 20> result();
|
||||
|
||||
/// Returns a raw 160-bit SHA1 hash for the given data.
|
||||
static std::array<uint8_t, 20> hash(ArrayRef<uint8_t> Data);
|
||||
@ -68,14 +68,13 @@ private:
|
||||
uint8_t BufferOffset;
|
||||
} InternalState;
|
||||
|
||||
// Internal copy of the hash, populated and accessed on calls to result()
|
||||
uint32_t HashResult[HASH_LENGTH / 4];
|
||||
|
||||
// Helper
|
||||
void writebyte(uint8_t data);
|
||||
void hashBlock();
|
||||
void addUncounted(uint8_t data);
|
||||
void pad();
|
||||
|
||||
void final(std::array<uint32_t, HASH_LENGTH / 4> &HashResult);
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
@ -43,17 +43,17 @@ public:
|
||||
/// Digest more data.
|
||||
void update(StringRef Str);
|
||||
|
||||
/// Return a reference to the current raw 256-bits SHA256 for the digested
|
||||
/// Return the current raw 256-bits SHA256 for the digested
|
||||
/// data since the last call to init(). This call will add data to the
|
||||
/// internal state and as such is not suited for getting an intermediate
|
||||
/// result (see result()).
|
||||
StringRef final();
|
||||
std::array<uint8_t, 32> final();
|
||||
|
||||
/// Return a reference to the current raw 256-bits SHA256 for the digested
|
||||
/// Return the current raw 256-bits SHA256 for the digested
|
||||
/// data since the last call to init(). This is suitable for getting the
|
||||
/// SHA256 at any time without invalidating the internal state so that more
|
||||
/// calls can be made into update.
|
||||
StringRef result();
|
||||
std::array<uint8_t, 32> result();
|
||||
|
||||
/// Returns a raw 256-bit SHA256 hash for the given data.
|
||||
static std::array<uint8_t, 32> hash(ArrayRef<uint8_t> Data);
|
||||
@ -75,14 +75,13 @@ private:
|
||||
uint8_t BufferOffset;
|
||||
} InternalState;
|
||||
|
||||
// Internal copy of the hash, populated and accessed on calls to result()
|
||||
uint32_t HashResult[HASH_LENGTH / 4];
|
||||
|
||||
// Helper
|
||||
void writebyte(uint8_t data);
|
||||
void hashBlock();
|
||||
void addUncounted(uint8_t data);
|
||||
void pad();
|
||||
|
||||
void final(std::array<uint32_t, HASH_LENGTH / 4> &HashResult);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
@ -30,7 +30,7 @@ class raw_sha1_ostream : public raw_ostream {
|
||||
|
||||
public:
|
||||
/// Return the current SHA1 hash for the content of the stream
|
||||
StringRef sha1() {
|
||||
std::array<uint8_t, 20> sha1() {
|
||||
flush();
|
||||
return State.result();
|
||||
}
|
||||
|
@ -903,7 +903,7 @@ Error BitcodeAnalyzer::parseBlock(unsigned BlockID, unsigned IndentLevel,
|
||||
else {
|
||||
// Recompute the hash and compare it to the one in the bitcode
|
||||
SHA1 Hasher;
|
||||
StringRef Hash;
|
||||
std::array<uint8_t, 20> Hash;
|
||||
Hasher.update(*CheckHash);
|
||||
{
|
||||
int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos;
|
||||
@ -911,14 +911,14 @@ Error BitcodeAnalyzer::parseBlock(unsigned BlockID, unsigned IndentLevel,
|
||||
Hasher.update(ArrayRef<uint8_t>(Ptr, BlockSize));
|
||||
Hash = Hasher.result();
|
||||
}
|
||||
std::array<char, 20> RecordedHash;
|
||||
std::array<uint8_t, 20> RecordedHash;
|
||||
int Pos = 0;
|
||||
for (auto &Val : Record) {
|
||||
assert(!(Val >> 32) && "Unexpected high bits set");
|
||||
support::endian::write32be(&RecordedHash[Pos], Val);
|
||||
Pos += 4;
|
||||
}
|
||||
if (Hash == StringRef(RecordedHash.data(), RecordedHash.size()))
|
||||
if (Hash == RecordedHash)
|
||||
O->OS << " (match)";
|
||||
else
|
||||
O->OS << " (!mismatch!)";
|
||||
|
@ -4387,7 +4387,7 @@ void ModuleBitcodeWriter::writeModuleHash(size_t BlockStartPos) {
|
||||
uint32_t Vals[5];
|
||||
Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&(Buffer)[BlockStartPos],
|
||||
Buffer.size() - BlockStartPos));
|
||||
StringRef Hash = Hasher.result();
|
||||
std::array<uint8_t, 20> Hash = Hasher.result();
|
||||
for (int Pos = 0; Pos < 20; Pos += 4) {
|
||||
Vals[Pos / 4] = support::endian::read32be(Hash.data() + Pos);
|
||||
}
|
||||
|
@ -3536,6 +3536,6 @@ Optional<MD5::MD5Result> DwarfDebug::getMD5AsBytes(const DIFile *File) const {
|
||||
// An MD5 checksum is 16 bytes.
|
||||
std::string ChecksumString = fromHex(Checksum->Value);
|
||||
MD5::MD5Result CKMem;
|
||||
std::copy(ChecksumString.begin(), ChecksumString.end(), CKMem.Bytes.data());
|
||||
std::copy(ChecksumString.begin(), ChecksumString.end(), CKMem.data());
|
||||
return CKMem;
|
||||
}
|
||||
|
@ -76,5 +76,6 @@ GloballyHashedType::hashType(ArrayRef<uint8_t> RecordData,
|
||||
auto TrailingBytes = RecordData.drop_front(Off);
|
||||
S.update(TrailingBytes);
|
||||
|
||||
return {S.final().take_back(8)};
|
||||
std::array<uint8_t, 20> Hash = S.final();
|
||||
return {ArrayRef<uint8_t>(Hash).take_back(8)};
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
|
||||
errc::invalid_argument,
|
||||
"failed to parse file entry because the MD5 hash is invalid");
|
||||
std::uninitialized_copy_n(Value.getAsBlock().getValue().begin(), 16,
|
||||
FileEntry.Checksum.Bytes.begin());
|
||||
FileEntry.Checksum.begin());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -387,8 +387,7 @@ static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
|
||||
if (EmitMD5) {
|
||||
const MD5::MD5Result &Cksum = *DwarfFile.Checksum;
|
||||
MCOS->emitBinaryData(
|
||||
StringRef(reinterpret_cast<const char *>(Cksum.Bytes.data()),
|
||||
Cksum.Bytes.size()));
|
||||
StringRef(reinterpret_cast<const char *>(Cksum.data()), Cksum.size()));
|
||||
}
|
||||
if (HasSource) {
|
||||
if (LineStr)
|
||||
|
@ -3573,8 +3573,8 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
|
||||
if (HasMD5) {
|
||||
MD5::MD5Result Sum;
|
||||
for (unsigned i = 0; i != 8; ++i) {
|
||||
Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
|
||||
Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
|
||||
Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
|
||||
Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
|
||||
}
|
||||
CKMem = Sum;
|
||||
}
|
||||
|
@ -4907,8 +4907,8 @@ bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
|
||||
if (HasMD5) {
|
||||
MD5::MD5Result Sum;
|
||||
for (unsigned i = 0; i != 8; ++i) {
|
||||
Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
|
||||
Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
|
||||
Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
|
||||
Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
|
||||
}
|
||||
CKMem = Sum;
|
||||
}
|
||||
|
@ -570,7 +570,7 @@ void MachOWriter::writeCodeSignatureData() {
|
||||
static_cast<ssize_t>(CodeSignature.BlockSize)));
|
||||
SHA256 Hasher;
|
||||
Hasher.update(Block);
|
||||
StringRef Hash = Hasher.final();
|
||||
std::array<uint8_t, 32> Hash = Hasher.final();
|
||||
assert(Hash.size() == CodeSignature.HashSize);
|
||||
memcpy(CurrHashWritePosition, Hash.data(), CodeSignature.HashSize);
|
||||
CurrHashReadPosition += CodeSignature.BlockSize;
|
||||
|
@ -152,7 +152,7 @@ template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN>
|
||||
void BLAKE3::final(BLAKE3Result<NumBytes> &Result);
|
||||
|
||||
template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN>
|
||||
BLAKE3Result<NumBytes> final();
|
||||
BLAKE3Result<NumBytes> BLAKE3::final();
|
||||
```
|
||||
```c
|
||||
void llvm_blake3_hasher_finalize(
|
||||
|
@ -261,13 +261,13 @@ void MD5::final(MD5Result &Result) {
|
||||
support::endian::write32le(&Result[12], InternalState.d);
|
||||
}
|
||||
|
||||
StringRef MD5::final() {
|
||||
MD5::MD5Result MD5::final() {
|
||||
MD5Result Result;
|
||||
final(Result);
|
||||
return StringRef(reinterpret_cast<char *>(Result.Bytes.data()),
|
||||
Result.Bytes.size());
|
||||
return Result;
|
||||
}
|
||||
|
||||
StringRef MD5::result() {
|
||||
MD5::MD5Result MD5::result() {
|
||||
auto StateToRestore = InternalState;
|
||||
|
||||
auto Hash = final();
|
||||
@ -280,15 +280,15 @@ StringRef MD5::result() {
|
||||
|
||||
SmallString<32> MD5::MD5Result::digest() const {
|
||||
SmallString<32> Str;
|
||||
toHex(Bytes, /*LowerCase*/ true, Str);
|
||||
toHex(*this, /*LowerCase*/ true, Str);
|
||||
return Str;
|
||||
}
|
||||
|
||||
void MD5::stringifyResult(MD5Result &Result, SmallVectorImpl<char> &Str) {
|
||||
toHex(Result.Bytes, /*LowerCase*/ true, Str);
|
||||
toHex(Result, /*LowerCase*/ true, Str);
|
||||
}
|
||||
|
||||
std::array<uint8_t, 16> MD5::hash(ArrayRef<uint8_t> Data) {
|
||||
MD5::MD5Result MD5::hash(ArrayRef<uint8_t> Data) {
|
||||
MD5 Hash;
|
||||
Hash.update(Data);
|
||||
MD5::MD5Result Res;
|
||||
|
@ -263,7 +263,7 @@ void SHA1::pad() {
|
||||
addUncounted(InternalState.ByteCount << 3);
|
||||
}
|
||||
|
||||
StringRef SHA1::final() {
|
||||
void SHA1::final(std::array<uint32_t, HASH_LENGTH / 4> &HashResult) {
|
||||
// Pad to complete the last block
|
||||
pad();
|
||||
|
||||
@ -281,12 +281,19 @@ StringRef SHA1::final() {
|
||||
(((InternalState.State[i]) >> 24) & 0x000000ff);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return pointer to hash (20 characters)
|
||||
return StringRef((char *)HashResult, HASH_LENGTH);
|
||||
}
|
||||
|
||||
StringRef SHA1::result() {
|
||||
std::array<uint8_t, 20> SHA1::final() {
|
||||
union {
|
||||
std::array<uint32_t, HASH_LENGTH / 4> HashResult;
|
||||
std::array<uint8_t, HASH_LENGTH> ReturnResult;
|
||||
};
|
||||
static_assert(sizeof(HashResult) == sizeof(ReturnResult), "");
|
||||
final(HashResult);
|
||||
return ReturnResult;
|
||||
}
|
||||
|
||||
std::array<uint8_t, 20> SHA1::result() {
|
||||
auto StateToRestore = InternalState;
|
||||
|
||||
auto Hash = final();
|
||||
@ -301,9 +308,5 @@ StringRef SHA1::result() {
|
||||
std::array<uint8_t, 20> SHA1::hash(ArrayRef<uint8_t> Data) {
|
||||
SHA1 Hash;
|
||||
Hash.update(Data);
|
||||
StringRef S = Hash.final();
|
||||
|
||||
std::array<uint8_t, 20> Arr;
|
||||
memcpy(Arr.data(), S.data(), S.size());
|
||||
return Arr;
|
||||
return Hash.final();
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ void SHA256::pad() {
|
||||
addUncounted(len);
|
||||
}
|
||||
|
||||
StringRef SHA256::final() {
|
||||
void SHA256::final(std::array<uint32_t, HASH_LENGTH / 4> &HashResult) {
|
||||
// Pad to complete the last block
|
||||
pad();
|
||||
|
||||
@ -261,12 +261,19 @@ StringRef SHA256::final() {
|
||||
(((InternalState.State[i]) >> 24) & 0x000000ff);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return pointer to hash (32 characters)
|
||||
return StringRef((char *)HashResult, HASH_LENGTH);
|
||||
}
|
||||
|
||||
StringRef SHA256::result() {
|
||||
std::array<uint8_t, 32> SHA256::final() {
|
||||
union {
|
||||
std::array<uint32_t, HASH_LENGTH / 4> HashResult;
|
||||
std::array<uint8_t, HASH_LENGTH> ReturnResult;
|
||||
};
|
||||
static_assert(sizeof(HashResult) == sizeof(ReturnResult), "");
|
||||
final(HashResult);
|
||||
return ReturnResult;
|
||||
}
|
||||
|
||||
std::array<uint8_t, 32> SHA256::result() {
|
||||
auto StateToRestore = InternalState;
|
||||
|
||||
auto Hash = final();
|
||||
@ -281,11 +288,7 @@ StringRef SHA256::result() {
|
||||
std::array<uint8_t, 32> SHA256::hash(ArrayRef<uint8_t> Data) {
|
||||
SHA256 Hash;
|
||||
Hash.update(Data);
|
||||
StringRef S = Hash.final();
|
||||
|
||||
std::array<uint8_t, 32> Arr;
|
||||
memcpy(Arr.data(), S.data(), S.size());
|
||||
return Arr;
|
||||
return Hash.final();
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "llvm/Support/BLAKE3.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/HashBuilder.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
@ -59,6 +60,14 @@ TEST(BLAKE3Test, BLAKE3) {
|
||||
auto hashStr = toHex(hash);
|
||||
EXPECT_EQ(hashStr,
|
||||
"616F575A1B58D4C9797D4217B9730AE5E6EB319D76EDEF6549B46F4EFE31FF8B");
|
||||
|
||||
// Using generic HashBuilder.
|
||||
HashBuilder<BLAKE3, support::endianness::native> HashBuilder;
|
||||
HashBuilder.update(std::get<0>(testvectors[2]));
|
||||
BLAKE3Result<> HBHash1 = HashBuilder.final();
|
||||
BLAKE3Result<> HBHash2 = HashBuilder.result();
|
||||
EXPECT_EQ(std::get<1>(testvectors[2]), toHex(HBHash1));
|
||||
EXPECT_EQ(std::get<1>(testvectors[2]), toHex(HBHash2));
|
||||
}
|
||||
|
||||
TEST(BLAKE3Test, SmallerHashSize) {
|
||||
@ -73,6 +82,14 @@ TEST(BLAKE3Test, SmallerHashSize) {
|
||||
auto hashStr2 = toHex(hash2);
|
||||
EXPECT_EQ(hashStr1, hashStr2);
|
||||
EXPECT_EQ(hashStr1, "6437B3AC38465133FFB63B75273A8DB5");
|
||||
|
||||
// Using generic HashBuilder.
|
||||
HashBuilder<TruncatedBLAKE3<16>, support::endianness::native> HashBuilder;
|
||||
HashBuilder.update(Input);
|
||||
BLAKE3Result<16> hash3 = HashBuilder.final();
|
||||
BLAKE3Result<16> hash4 = HashBuilder.result();
|
||||
EXPECT_EQ(hashStr1, toHex(hash3));
|
||||
EXPECT_EQ(hashStr1, toHex(hash4));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -44,13 +44,15 @@ using HashBuilder = llvm::HashBuilder<typename HasherTAndEndianness::HasherT,
|
||||
HasherTAndEndianness::Endianness>;
|
||||
|
||||
template <typename HasherTAndEndianness, typename... Ts>
|
||||
static std::string hashWithBuilder(const Ts &...Args) {
|
||||
return HashBuilder<HasherTAndEndianness>().add(Args...).final().str();
|
||||
static typename HashBuilder<HasherTAndEndianness>::template HashResultTy<>
|
||||
hashWithBuilder(const Ts &...Args) {
|
||||
return HashBuilder<HasherTAndEndianness>().add(Args...).final();
|
||||
}
|
||||
|
||||
template <typename HasherTAndEndianness, typename... Ts>
|
||||
static std::string hashRangeWithBuilder(const Ts &...Args) {
|
||||
return HashBuilder<HasherTAndEndianness>().addRange(Args...).final().str();
|
||||
static typename HashBuilder<HasherTAndEndianness>::template HashResultTy<>
|
||||
hashRangeWithBuilder(const Ts &...Args) {
|
||||
return HashBuilder<HasherTAndEndianness>().addRange(Args...).final();
|
||||
}
|
||||
|
||||
// All the test infrastructure relies on the variadic helpers. Test them first.
|
||||
@ -102,7 +104,7 @@ TYPED_TEST(HashBuilderTest, AddHashableData) {
|
||||
auto SwappedData = llvm::support::endian::byte_swap(Data, E);
|
||||
Hasher.update(llvm::makeArrayRef(
|
||||
reinterpret_cast<const uint8_t *>(&SwappedData), sizeof(Data)));
|
||||
return static_cast<std::string>(Hasher.final());
|
||||
return Hasher.final();
|
||||
};
|
||||
|
||||
char C = 'c';
|
||||
|
@ -62,7 +62,7 @@ TEST(MD5HashTest, MD5) {
|
||||
std::array<uint8_t, 16> Vec = MD5::hash(Input);
|
||||
MD5::MD5Result MD5Res;
|
||||
SmallString<32> Res;
|
||||
memcpy(MD5Res.Bytes.data(), Vec.data(), Vec.size());
|
||||
memcpy(MD5Res.data(), Vec.data(), Vec.size());
|
||||
MD5::stringifyResult(MD5Res, Res);
|
||||
EXPECT_EQ(Res, "c3fcd3d76192e4007dfb496cca67e13b");
|
||||
EXPECT_EQ(0x3be167ca6c49fb7dULL, MD5Res.high());
|
||||
@ -79,10 +79,7 @@ TEST(MD5Test, FinalAndResultHelpers) {
|
||||
ReferenceHash.update("abcd");
|
||||
MD5::MD5Result ReferenceResult;
|
||||
ReferenceHash.final(ReferenceResult);
|
||||
StringRef ExpectedResult =
|
||||
StringRef(reinterpret_cast<char *>(ReferenceResult.Bytes.data()),
|
||||
ReferenceResult.Bytes.size());
|
||||
EXPECT_EQ(Hash.result(), ExpectedResult);
|
||||
EXPECT_EQ(Hash.result(), ReferenceResult);
|
||||
}
|
||||
|
||||
Hash.update("xyz");
|
||||
@ -93,10 +90,7 @@ TEST(MD5Test, FinalAndResultHelpers) {
|
||||
ReferenceHash.update("xyz");
|
||||
MD5::MD5Result ReferenceResult;
|
||||
ReferenceHash.final(ReferenceResult);
|
||||
StringRef ExpectedResult =
|
||||
StringRef(reinterpret_cast<char *>(ReferenceResult.Bytes.data()),
|
||||
ReferenceResult.Bytes.size());
|
||||
EXPECT_EQ(Hash.final(), ExpectedResult);
|
||||
EXPECT_EQ(Hash.final(), ReferenceResult);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
@ -20,7 +20,7 @@ using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
static std::string toHex(StringRef Input) {
|
||||
static std::string toHex(ArrayRef<uint8_t> Input) {
|
||||
static const char *const LUT = "0123456789abcdef";
|
||||
size_t Length = Input.size();
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static std::string toHex(StringRef Input) {
|
||||
static std::string toHex(ArrayRef<uint8_t> Input) {
|
||||
static const char *const LUT = "0123456789ABCDEF";
|
||||
size_t Length = Input.size();
|
||||
|
||||
@ -39,7 +39,7 @@ TEST(raw_sha1_ostreamTest, Basic) {
|
||||
TEST(sha1_hash_test, Basic) {
|
||||
ArrayRef<uint8_t> Input((const uint8_t *)"Hello World!", 12);
|
||||
std::array<uint8_t, 20> Vec = SHA1::hash(Input);
|
||||
std::string Hash = toHex({(const char *)Vec.data(), 20});
|
||||
std::string Hash = toHex(Vec);
|
||||
ASSERT_EQ("2EF7BDE608CE5404E97D5F042F95F89F1C232871", Hash);
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ private:
|
||||
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&data), sizeof(T)));
|
||||
}
|
||||
|
||||
SmallString<20> hash;
|
||||
std::array<uint8_t, 20> hash;
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
Loading…
x
Reference in New Issue
Block a user