diff --git a/llvm/include/llvm/Support/MD5.h b/llvm/include/llvm/Support/MD5.h index c19f6989fe25ea..3b960cd4fd8804 100644 --- a/llvm/include/llvm/Support/MD5.h +++ b/llvm/include/llvm/Support/MD5.h @@ -78,6 +78,14 @@ class MD5 { /// 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 a reference to 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(); + /// 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, SmallString<32> &Str); @@ -101,6 +109,8 @@ class MD5 { MD5_u32plus block[16]; } InternalState; + MD5Result Result; + const uint8_t *body(ArrayRef Data); }; diff --git a/llvm/lib/Support/MD5.cpp b/llvm/lib/Support/MD5.cpp index a2612b0c19ace9..9dceb4d418cde2 100644 --- a/llvm/lib/Support/MD5.cpp +++ b/llvm/lib/Support/MD5.cpp @@ -262,6 +262,23 @@ void MD5::final(MD5Result &Result) { support::endian::write32le(&Result[12], InternalState.d); } +StringRef MD5::final() { + final(Result); + return StringRef(reinterpret_cast(Result.Bytes.data()), + Result.Bytes.size()); +} + +StringRef MD5::result() { + auto StateToRestore = InternalState; + + auto Hash = final(); + + // Restore the state + InternalState = StateToRestore; + + return Hash; +} + SmallString<32> MD5::MD5Result::digest() const { SmallString<32> Str; raw_svector_ostream Res(Str); diff --git a/llvm/unittests/Support/MD5Test.cpp b/llvm/unittests/Support/MD5Test.cpp index 3a24e1fa69796b..8eb4d3422cb62d 100644 --- a/llvm/unittests/Support/MD5Test.cpp +++ b/llvm/unittests/Support/MD5Test.cpp @@ -68,4 +68,35 @@ TEST(MD5HashTest, MD5) { EXPECT_EQ(0x3be167ca6c49fb7dULL, MD5Res.high()); EXPECT_EQ(0x00e49261d7d3fcc3ULL, MD5Res.low()); } + +TEST(MD5Test, FinalAndResultHelpers) { + MD5 Hash; + + Hash.update("abcd"); + + { + MD5 ReferenceHash; + ReferenceHash.update("abcd"); + MD5::MD5Result ReferenceResult; + ReferenceHash.final(ReferenceResult); + StringRef ExpectedResult = + StringRef(reinterpret_cast(ReferenceResult.Bytes.data()), + ReferenceResult.Bytes.size()); + EXPECT_EQ(Hash.result(), ExpectedResult); + } + + Hash.update("xyz"); + + { + MD5 ReferenceHash; + ReferenceHash.update("abcd"); + ReferenceHash.update("xyz"); + MD5::MD5Result ReferenceResult; + ReferenceHash.final(ReferenceResult); + StringRef ExpectedResult = + StringRef(reinterpret_cast(ReferenceResult.Bytes.data()), + ReferenceResult.Bytes.size()); + EXPECT_EQ(Hash.final(), ExpectedResult); + } } +} // namespace