summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Support/MD5.h15
-rw-r--r--lib/Support/MD5.cpp52
-rw-r--r--unittests/Support/MD5Test.cpp42
3 files changed, 85 insertions, 24 deletions
diff --git a/include/llvm/Support/MD5.h b/include/llvm/Support/MD5.h
index fd52ca54e1..9d306993f0 100644
--- a/include/llvm/Support/MD5.h
+++ b/include/llvm/Support/MD5.h
@@ -28,10 +28,13 @@
#ifndef LLVM_SYSTEM_MD5_H
#define LLVM_SYSTEM_MD5_H
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
+template <typename T> class ArrayRef;
+
class MD5 {
// Any 32-bit or wider unsigned integer data type will do.
typedef uint32_t MD5_u32plus;
@@ -41,17 +44,21 @@ class MD5 {
unsigned char buffer[64];
MD5_u32plus block[16];
- public:
+public:
+ typedef unsigned char MD5Result[16];
+
MD5();
/// \brief Updates the hash for arguments provided.
- void Update(void *data, unsigned long size);
+ void update(ArrayRef<unsigned char> Data);
/// \brief Finishes off the hash and puts the result in result.
- void Final(unsigned char *result);
+ void final(MD5Result &result);
+
+ static void stringifyResult(MD5Result &Res, SmallString<32> &Str);
private:
- void *body(void *data, unsigned long size);
+ const unsigned char *body(ArrayRef<unsigned char> Data);
};
}
diff --git a/lib/Support/MD5.cpp b/lib/Support/MD5.cpp
index 6dfbe7a464..6cd040bd1b 100644
--- a/lib/Support/MD5.cpp
+++ b/lib/Support/MD5.cpp
@@ -37,7 +37,10 @@
* compile-time configuration.
*/
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/MD5.h"
+#include "llvm/Support/raw_ostream.h"
#include <cstring>
// The basic MD5 functions.
@@ -69,12 +72,13 @@ namespace llvm {
/// \brief This processes one or more 64-byte data blocks, but does NOT update
///the bit counters. There are no alignment requirements.
-void *MD5::body(void *data, unsigned long size) {
- unsigned char *ptr;
+const unsigned char *MD5::body(ArrayRef<unsigned char> Data) {
+ const unsigned char *ptr;
MD5_u32plus a, b, c, d;
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+ unsigned long Size = Data.size();
- ptr = (unsigned char *)data;
+ ptr = Data.data();
a = this->a;
b = this->b;
@@ -165,7 +169,7 @@ void *MD5::body(void *data, unsigned long size) {
d += saved_d;
ptr += 64;
- } while (size -= 64);
+ } while (Size -= 64);
this->a = a;
this->b = b;
@@ -180,42 +184,44 @@ MD5::MD5()
}
/// Incrementally add \p size of \p data to the hash.
-void MD5::Update(void *data, unsigned long size) {
+void MD5::update(ArrayRef<unsigned char> Data) {
MD5_u32plus saved_lo;
unsigned long used, free;
+ const unsigned char *Ptr = Data.data();
+ unsigned long Size = Data.size();
saved_lo = lo;
- if ((lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ if ((lo = (saved_lo + Size) & 0x1fffffff) < saved_lo)
hi++;
- hi += size >> 29;
+ hi += Size >> 29;
used = saved_lo & 0x3f;
if (used) {
free = 64 - used;
- if (size < free) {
- memcpy(&buffer[used], data, size);
+ if (Size < free) {
+ memcpy(&buffer[used], Ptr, Size);
return;
}
- memcpy(&buffer[used], data, free);
- data = (unsigned char *)data + free;
- size -= free;
- body(buffer, 64);
+ memcpy(&buffer[used], Ptr, free);
+ Ptr = Ptr + free;
+ Size -= free;
+ body(ArrayRef<unsigned char>(buffer, 64));
}
- if (size >= 64) {
- data = body(data, size & ~(unsigned long) 0x3f);
- size &= 0x3f;
+ if (Size >= 64) {
+ Ptr = body(ArrayRef<unsigned char>(Ptr, Size & ~(unsigned long) 0x3f));
+ Size &= 0x3f;
}
- memcpy(buffer, data, size);
+ memcpy(buffer, Ptr, Size);
}
/// \brief Finish the hash and place the resulting hash into \p result.
/// \param result is assumed to be a minimum of 16-bytes in size.
-void MD5::Final(unsigned char *result) {
+void MD5::final(MD5Result &result) {
unsigned long used, free;
used = lo & 0x3f;
@@ -226,7 +232,7 @@ void MD5::Final(unsigned char *result) {
if (free < 8) {
memset(&buffer[used], 0, free);
- body(buffer, 64);
+ body(ArrayRef<unsigned char>(buffer, 64));
used = 0;
free = 64;
}
@@ -243,7 +249,7 @@ void MD5::Final(unsigned char *result) {
buffer[62] = hi >> 16;
buffer[63] = hi >> 24;
- body(buffer, 64);
+ body(ArrayRef<unsigned char>(buffer, 64));
result[0] = a;
result[1] = a >> 8;
@@ -263,4 +269,10 @@ void MD5::Final(unsigned char *result) {
result[15] = d >> 24;
}
+void MD5::stringifyResult(MD5Result &result, SmallString<32> &Str) {
+ raw_svector_ostream Res(Str);
+ for (int i = 0; i < 16; ++i)
+ Res << format("%.2x", result[i]);
+}
+
}
diff --git a/unittests/Support/MD5Test.cpp b/unittests/Support/MD5Test.cpp
new file mode 100644
index 0000000000..159ae3e463
--- /dev/null
+++ b/unittests/Support/MD5Test.cpp
@@ -0,0 +1,42 @@
+//===- llvm/unittest/Support/MD5Test.cpp - MD5 tests ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements unit tests for the MD5 functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/MD5.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+void TestMD5Sum(ArrayRef<unsigned char> Input, StringRef Final) {
+ MD5 Hash;
+ Hash.update(Input);
+ MD5::MD5Result MD5Res;
+ Hash.final(MD5Res);
+ SmallString<32> Res;
+ MD5::stringifyResult(MD5Res, Res);
+ EXPECT_EQ(Res, Final);
+}
+
+TEST(MD5Test, MD5) {
+ TestMD5Sum(ArrayRef<unsigned char>((const unsigned char *)"", (size_t) 0),
+ "d41d8cd98f00b204e9800998ecf8427e");
+ TestMD5Sum(ArrayRef<unsigned char>((const unsigned char *)"a", (size_t) 1),
+ "0cc175b9c0f1b6a831c399e269772661");
+ TestMD5Sum(ArrayRef<unsigned char>(
+ (const unsigned char *)"abcdefghijklmnopqrstuvwxyz",
+ (size_t) 26),
+ "c3fcd3d76192e4007dfb496cca67e13b");
+}
+}