From: Eric Christopher Date: Fri, 24 May 2013 23:08:17 +0000 (+0000) Subject: ArrayRef-ize MD5 and clean up a few variable names. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=f7306f224e7f85c2690256636613422c4a7b8230;p=oota-llvm.git ArrayRef-ize MD5 and clean up a few variable names. Add a stringize method to make dumping a bit easier, and add a testcase exercising a few different paths. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182692 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Support/MD5.h b/include/llvm/Support/MD5.h index fd52ca54e19..9d306993f0e 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 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 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 Data); }; } diff --git a/lib/Support/MD5.cpp b/lib/Support/MD5.cpp index 6dfbe7a4645..6cd040bd1b5 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 // 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 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 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(buffer, 64)); } - if (size >= 64) { - data = body(data, size & ~(unsigned long) 0x3f); - size &= 0x3f; + if (Size >= 64) { + Ptr = body(ArrayRef(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(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(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 00000000000..159ae3e4631 --- /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 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((const unsigned char *)"", (size_t) 0), + "d41d8cd98f00b204e9800998ecf8427e"); + TestMD5Sum(ArrayRef((const unsigned char *)"a", (size_t) 1), + "0cc175b9c0f1b6a831c399e269772661"); + TestMD5Sum(ArrayRef( + (const unsigned char *)"abcdefghijklmnopqrstuvwxyz", + (size_t) 26), + "c3fcd3d76192e4007dfb496cca67e13b"); +} +}