diff options
author | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-08 18:25:47 +0300 |
---|---|---|
committer | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-08 18:25:47 +0300 |
commit | a3ac8a71f16e0db7d50d5b1235466ff754e0d228 (patch) | |
tree | 8433eb84ffae296ccb9ae094d08491c86c48bdb1 /library/cpp | |
parent | 60312eaed2e51caa7ed482270d3545a9d27cb284 (diff) | |
download | ydb-a3ac8a71f16e0db7d50d5b1235466ff754e0d228.tar.gz |
intermediate changes
ref:f398132a6a7101a031da4a85ff8dc9f360af7d8a
Diffstat (limited to 'library/cpp')
-rw-r--r-- | library/cpp/digest/md5/bench/main.cpp | 13 | ||||
-rw-r--r-- | library/cpp/digest/md5/bench/ya.make | 2 | ||||
-rw-r--r-- | library/cpp/digest/md5/md5.cpp | 198 | ||||
-rw-r--r-- | library/cpp/digest/md5/md5.h | 48 | ||||
-rw-r--r-- | library/cpp/digest/md5/md5_ut.cpp | 8 | ||||
-rw-r--r-- | library/cpp/testing/unittest/registar.h | 17 | ||||
-rw-r--r-- | library/cpp/testing/unittest/registar_ut.cpp | 13 |
7 files changed, 159 insertions, 140 deletions
diff --git a/library/cpp/digest/md5/bench/main.cpp b/library/cpp/digest/md5/bench/main.cpp index 8f6386d8a1..70672e6741 100644 --- a/library/cpp/digest/md5/bench/main.cpp +++ b/library/cpp/digest/md5/bench/main.cpp @@ -1,16 +1,15 @@ -#include <library/cpp/testing/benchmark/bench.h> -#include <library/cpp/digest/md5/md5.h> +#include <benchmark/benchmark.h> -#include <util/generic/xrange.h> +#include <library/cpp/digest/md5/md5.h> #define MD5_DEF(N) \ - Y_CPU_BENCHMARK(MD5_##N, iface) { \ + static void MD5Benchmark_##N(benchmark::State& st) { \ char buf[N]; \ - for (const auto i : xrange(iface.Iterations())) { \ - Y_UNUSED(i); \ + for (auto _ : st) { \ Y_DO_NOT_OPTIMIZE_AWAY(MD5().Update(buf, sizeof(buf))); \ } \ - } + } \ + BENCHMARK(MD5Benchmark_##N); MD5_DEF(32) MD5_DEF(64) diff --git a/library/cpp/digest/md5/bench/ya.make b/library/cpp/digest/md5/bench/ya.make index ad78159d8e..5c3e3c1c42 100644 --- a/library/cpp/digest/md5/bench/ya.make +++ b/library/cpp/digest/md5/bench/ya.make @@ -1,4 +1,4 @@ -Y_BENCHMARK() +G_BENCHMARK() OWNER( pg diff --git a/library/cpp/digest/md5/md5.cpp b/library/cpp/digest/md5/md5.cpp index 27af7f88d7..24a5b69eef 100644 --- a/library/cpp/digest/md5/md5.cpp +++ b/library/cpp/digest/md5/md5.cpp @@ -1,19 +1,17 @@ #include "md5.h" -#include <contrib/libs/nayuki_md5/md5.h> +#include <library/cpp/string_utils/base64/base64.h> -#include <util/generic/strbuf.h> -#include <util/generic/string.h> #include <util/stream/input.h> #include <util/stream/file.h> -#include <library/cpp/string_utils/base64/base64.h> #include <util/string/hex.h> -#include <cstring> -#include <cstdlib> +#include <contrib/libs/nayuki_md5/md5.h> namespace { + constexpr size_t MD5_BLOCK_LENGTH = 64; + constexpr size_t MD5_PADDING_SHIFT = 56; constexpr size_t MD5_HEX_DIGEST_LENGTH = 32; struct TMd5Stream: public IOutputStream { @@ -28,6 +26,14 @@ namespace { MD5* M_; }; + + inline TArrayRef<const ui8> MakeUnsignedArrayRef(const void* data, const size_t size) { + return MakeArrayRef(static_cast<const ui8*>(data), size); + } + + inline TArrayRef<const ui8> MakeUnsignedArrayRef(const TArrayRef<const char>& data) { + return MakeUnsignedArrayRef(data.data(), data.size()); + } } char* MD5::File(const char* filename, char* buf) { @@ -51,30 +57,23 @@ TString MD5::File(const TString& filename) { return buf; } -char* MD5::Data(const void* data, size_t len, char* buf) { - MD5 md5; - md5.Update(data, len); - return md5.End(buf); +char* MD5::Data(const TArrayRef<const ui8>& data, char* buf) { + return MD5().Update(data).End(buf); } -TString MD5::Data(TArrayRef<ui8> data) { - MD5 md5; - md5.Update(data.data(), data.size()); +char* MD5::Data(const void* data, size_t len, char* buf) { + return Data(MakeUnsignedArrayRef(data, len), buf); +} +TString MD5::Data(const TArrayRef<const ui8>& data) { TString buf; buf.ReserveAndResize(MD5_HEX_DIGEST_LENGTH); - md5.End(buf.begin()); + Data(data, buf.begin()); return buf; } TString MD5::Data(TStringBuf data) { - MD5 md5; - md5.Update(data.data(), data.size()); - - TString buf; - buf.ReserveAndResize(MD5_HEX_DIGEST_LENGTH); - md5.End(buf.begin()); - return buf; + return Data(MakeUnsignedArrayRef(data)); } char* MD5::Stream(IInputStream* in, char* buf) { @@ -89,27 +88,7 @@ MD5& MD5::Update(IInputStream* in) { return *this; } -static inline void MD5Transform(ui32 state[4], const unsigned char block[64]) { - return md5_compress((uint32_t*)state, (const ui8*)block); -} - -/* - * Encodes input (ui32) into output (unsigned char). Assumes len is - * a multiple of 4. - */ - -static void Encode(unsigned char* output, ui32* input, unsigned int len) { - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff); - } -} - -static unsigned char PADDING[64] = { +static const ui8 PADDING[MD5_BLOCK_LENGTH] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -117,7 +96,8 @@ static unsigned char PADDING[64] = { /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void MD5::Init() { - Count[0] = Count[1] = 0; + BufferSize = 0; + StreamSize = 0; /* Load magic initialization constants. */ State[0] = 0x67452301; State[1] = 0xefcdab89; @@ -131,27 +111,30 @@ void MD5::Init() { * context. */ -void MD5::UpdatePart(const void* inputPtr, unsigned int inputLen) { - const unsigned char* input = (const unsigned char*)inputPtr; - unsigned int i, index, partLen; - /* Compute number of bytes mod 64 */ - index = (unsigned int)((Count[0] >> 3) & 0x3F); - /* Update number of bits */ - if ((Count[0] += ((ui32)inputLen << 3)) < ((ui32)inputLen << 3)) - Count[1]++; - Count[1] += ((ui32)inputLen >> 29); - partLen = 64 - index; - /* Transform as many times as possible. */ - if (inputLen >= partLen) { - memcpy((void*)&Buffer[index], (const void*)input, partLen); - MD5Transform(State, Buffer); - for (i = partLen; i + 63 < inputLen; i += 64) - MD5Transform(State, &input[i]); - index = 0; - } else - i = 0; - /* Buffer remaining input */ - memcpy((void*)&Buffer[index], (const void*)&input[i], inputLen - i); +void MD5::UpdatePart(TArrayRef<const ui8> data) { + /* Count input bytes */ + StreamSize += data.size(); + if (BufferSize > 0) { + /* Filling remaining buffer */ + const ui8 freeBufferSize = MD5_BLOCK_LENGTH - BufferSize; + const ui8 partLen = data.size() >= freeBufferSize ? freeBufferSize : data.size(); + memcpy(&Buffer[BufferSize], data.data(), partLen); + BufferSize += partLen; + data = data.Slice(partLen); + if (BufferSize == MD5_BLOCK_LENGTH) { + /* Buffer is full and ready for hashing */ + md5_compress(State, Buffer); + BufferSize = 0; + } + } + /* Processing input by chanks */ + while (data.size() >= MD5_BLOCK_LENGTH) { + md5_compress(State, data.data()); + data = data.Slice(MD5_BLOCK_LENGTH); + } + /* Save remaining input in buffer */ + memcpy(Buffer, data.data(), data.size()); + BufferSize += data.size(); } /* @@ -159,16 +142,19 @@ void MD5::UpdatePart(const void* inputPtr, unsigned int inputLen) { */ void MD5::Pad() { - unsigned char bits[8]; - unsigned int index, padLen; - /* Save number of bits */ - Encode(bits, Count, 8); - /* Pad out to 56 mod 64. */ - index = (unsigned int)((Count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - Update(PADDING, padLen); - /* Append length (before padding) */ - Update(bits, 8); + size_t streamSize = StreamSize; + + const size_t paddingSize = (MD5_PADDING_SHIFT > BufferSize) ? (MD5_PADDING_SHIFT - BufferSize) : (MD5_PADDING_SHIFT + MD5_BLOCK_LENGTH - BufferSize); + Update(PADDING, paddingSize); + + // Size of stream in bits + // If size greater than 2^64 - 1 only lower 64 bits used + streamSize <<= 3; + for (int i = 0; i < 8; ++i, streamSize >>= 8) { + // Storing in reverse order + Buffer[MD5_PADDING_SHIFT + i] = static_cast<ui8>(streamSize & 0xFFU); + } + md5_compress(State, Buffer); } /* @@ -176,36 +162,35 @@ void MD5::Pad() { * the message digest and zeroizing the context. */ -unsigned char* MD5::Final(unsigned char digest[16]) { +ui8* MD5::Final(ui8 digest[16]) { /* Do padding. */ Pad(); /* Store state in digest */ - Encode(digest, State, 16); + memcpy(digest, State, 16); /* Zeroize sensitive information. */ - memset((void*)this, 0, sizeof(*this)); + Init(); return digest; } char* MD5::End(char* buf) { - unsigned char digest[16]; static const char hex[] = "0123456789abcdef"; + ui8 digest[16]; if (!buf) buf = (char*)malloc(33); if (!buf) return nullptr; Final(digest); - int i = 0; - for (; i < 16; i++) { - buf[i + i] = hex[digest[i] >> 4]; - buf[i + i + 1] = hex[digest[i] & 0x0f]; + for (ui8 i = 0; i < MD5_HEX_DIGEST_LENGTH / 2; i++) { + buf[i * 2] = hex[digest[i] >> 4]; + buf[i * 2 + 1] = hex[digest[i] & 0x0f]; } - buf[i + i] = '\0'; + buf[32] = '\0'; return buf; } char* MD5::End_b64(char* buf) { - unsigned char digest[16]; + ui8 digest[16]; if (!buf) buf = (char*)malloc(25); if (!buf) @@ -217,7 +202,7 @@ char* MD5::End_b64(char* buf) { } ui64 MD5::EndHalfMix() { - unsigned char digest[16]; + ui8 digest[16]; Final(digest); ui64 res = 0; for (int i = 3; i >= 0; i--) { @@ -227,40 +212,47 @@ ui64 MD5::EndHalfMix() { return res; } -TString MD5::Calc(const TStringBuf& data) { - TString result; - result.resize(32); +TString MD5::Calc(TStringBuf data) { + return Calc(MakeUnsignedArrayRef(data)); +} - Data((const unsigned char*)data.data(), data.size(), result.begin()); +TString MD5::Calc(const TArrayRef<const ui8>& data) { + return Data(data); +} - return result; +TString MD5::CalcRaw(TStringBuf data) { + return CalcRaw(MakeUnsignedArrayRef(data)); } -TString MD5::CalcRaw(const TStringBuf& data) { +TString MD5::CalcRaw(const TArrayRef<const ui8>& data) { TString result; - result.resize(16); - MD5 md5; - md5.Update(data.data(), data.size()); - md5.Final(reinterpret_cast<unsigned char*>(result.begin())); + result.ReserveAndResize(16); + MD5().Update(data).Final(reinterpret_cast<ui8*>(result.begin())); return result; } ui64 MD5::CalcHalfMix(const char* data, size_t len) { - MD5 md5; - md5.Update(data, len); - return md5.EndHalfMix(); + return CalcHalfMix(MakeUnsignedArrayRef(data, len)); +} + +ui64 MD5::CalcHalfMix(TStringBuf data) { + return CalcHalfMix(MakeUnsignedArrayRef(data)); +} + +ui64 MD5::CalcHalfMix(const TArrayRef<const ui8>& data) { + return MD5().Update(data).EndHalfMix(); } -ui64 MD5::CalcHalfMix(const TStringBuf& data) { - return CalcHalfMix(data.data(), data.size()); +bool MD5::IsMD5(TStringBuf data) { + return IsMD5(MakeUnsignedArrayRef(data)); } -bool MD5::IsMD5(const TStringBuf& data) { +bool MD5::IsMD5(const TArrayRef<const ui8>& data) { if (data.size() != 32) { return false; } - for (const char *p = data.data(), *e = data.data() + data.size(); p != e; ++p) { - if (Char2DigitTable[(unsigned char)*p] == '\xff') { + for (const ui8 *p = data.data(), *e = data.data() + data.size(); p != e; ++p) { + if (Char2DigitTable[*p] == '\xff') { return false; } } diff --git a/library/cpp/digest/md5/md5.h b/library/cpp/digest/md5/md5.h index 1568567e3c..2c17aa0518 100644 --- a/library/cpp/digest/md5/md5.h +++ b/library/cpp/digest/md5/md5.h @@ -1,7 +1,5 @@ #pragma once -#include <util/system/defaults.h> -#include <util/generic/string.h> #include <util/generic/array_ref.h> #include <util/generic/strbuf.h> @@ -16,26 +14,20 @@ public: void Init(); inline MD5& Update(const void* data, size_t len) { - const char* buf = (const char*)data; - - while (len) { - // NOTE: we don't want buffSz to be near Max<unsigned int>() - // because otherwise integer overflow might happen in UpdatePart - const unsigned int buffSz = Min(size_t(Max<unsigned int>() / 2), len); - - UpdatePart(buf, buffSz); - buf += buffSz; - len -= buffSz; - } - return *this; + return Update(MakeArrayRef(static_cast<const ui8*>(data), len)); } - inline MD5& Update(const TStringBuf& data) { + inline MD5& Update(TStringBuf data) { return Update(data.data(), data.size()); } + inline MD5& Update(const TArrayRef<const ui8> data) { + UpdatePart(data); + return *this; + } + void Pad(); - unsigned char* Final(unsigned char[16]); + ui8* Final(ui8[16]); // buf must be char[33]; char* End(char* buf); @@ -57,23 +49,29 @@ public: static TString File(const TString& filename); static char* Data(const void* data, size_t len, char* buf); - static TString Data(TArrayRef<ui8> data); + static char* Data(const TArrayRef<const ui8>& data, char* buf); + static TString Data(const TArrayRef<const ui8>& data); static TString Data(TStringBuf data); static char* Stream(IInputStream* in, char* buf); - static TString Calc(const TStringBuf& data); // 32-byte hex-encoded - static TString CalcRaw(const TStringBuf& data); // 16-byte raw + static TString Calc(TStringBuf data); // 32-byte hex-encoded + static TString Calc(const TArrayRef<const ui8>& data); // 32-byte hex-encoded + static TString CalcRaw(TStringBuf data); // 16-byte raw + static TString CalcRaw(const TArrayRef<const ui8>& data); // 16-byte raw - static ui64 CalcHalfMix(const TStringBuf& data); + static ui64 CalcHalfMix(TStringBuf data); + static ui64 CalcHalfMix(const TArrayRef<const ui8>& data); static ui64 CalcHalfMix(const char* data, size_t len); - static bool IsMD5(const TStringBuf& data); + static bool IsMD5(TStringBuf data); + static bool IsMD5(const TArrayRef<const ui8>& data); private: - void UpdatePart(const void* data, unsigned int len); + void UpdatePart(TArrayRef<const ui8> data); private: - ui32 State[4]; /* state (ABCD) */ - ui32 Count[2]; /* number of bits, modulo 2^64 (lsb first) */ - unsigned char Buffer[64]; /* input buffer */ + ui8 BufferSize; /* size of buffer */ + ui8 Buffer[64]; /* input buffer */ + ui32 State[4]; /* state (ABCD) */ + ui64 StreamSize; /* total bytes in input stream */ }; diff --git a/library/cpp/digest/md5/md5_ut.cpp b/library/cpp/digest/md5/md5_ut.cpp index fecccca9ba..1c3e4ad0a9 100644 --- a/library/cpp/digest/md5/md5_ut.cpp +++ b/library/cpp/digest/md5/md5_ut.cpp @@ -18,11 +18,11 @@ Y_UNIT_TEST_SUITE(TMD5Test) { TString s(r.End(rs)); s.to_lower(); - UNIT_ASSERT_EQUAL(s, TStringBuf("3ac00dd696b966fd74deee3c35a59d8f")); + UNIT_ASSERT_NO_DIFF(s, TStringBuf("3ac00dd696b966fd74deee3c35a59d8f")); TString result = r.Calc(TStringBuf(b)); result.to_lower(); - UNIT_ASSERT_EQUAL(result, TStringBuf("3ac00dd696b966fd74deee3c35a59d8f")); + UNIT_ASSERT_NO_DIFF(result, TStringBuf("3ac00dd696b966fd74deee3c35a59d8f")); } Y_UNIT_TEST(TestFile) { @@ -39,10 +39,10 @@ Y_UNIT_TEST_SUITE(TMD5Test) { TString fileHash = MD5::File(tmpFile.data(), fileBuf); TString memoryHash = MD5::Data((const unsigned char*)s.data(), s.size(), memBuf); - UNIT_ASSERT_EQUAL(fileHash, memoryHash); + UNIT_ASSERT_NO_DIFF(fileHash, memoryHash); fileHash = MD5::File(tmpFile); - UNIT_ASSERT_EQUAL(fileHash, memoryHash); + UNIT_ASSERT_NO_DIFF(fileHash, memoryHash); NFs::Remove(tmpFile); fileHash = MD5::File(tmpFile); diff --git a/library/cpp/testing/unittest/registar.h b/library/cpp/testing/unittest/registar.h index 332485bdf3..44517a0092 100644 --- a/library/cpp/testing/unittest/registar.h +++ b/library/cpp/testing/unittest/registar.h @@ -627,6 +627,23 @@ public: \ // Assert that a specific exception is thrown #define UNIT_ASSERT_EXCEPTION(A, E) UNIT_ASSERT_EXCEPTION_C(A, E, "") +#define UNIT_ASSERT_NO_EXCEPTION_RESULT_C(A, C) \ + [&] () mutable -> decltype(A) { \ + static_assert(!std::is_void_v<decltype(A)>); \ + try { return (A); } \ + catch (const ::NUnitTest::TAssertException&) { throw; } \ + catch (...) { \ + UNIT_FAIL_IMPL( \ + "exception-free assertion failed", \ + Sprintf("%s throws %s\nException message: %s", \ + #A, (::TStringBuilder() << C).data(), \ + CurrentExceptionMessage().data())); \ + return decltype(A){}; \ + } \ + }() + +#define UNIT_ASSERT_NO_EXCEPTION_RESULT(A) UNIT_ASSERT_NO_EXCEPTION_RESULT_C(A, "") + #define UNIT_ASSERT_NO_EXCEPTION_C(A, C) \ do { \ try { \ diff --git a/library/cpp/testing/unittest/registar_ut.cpp b/library/cpp/testing/unittest/registar_ut.cpp index aada471030..1f36d53abb 100644 --- a/library/cpp/testing/unittest/registar_ut.cpp +++ b/library/cpp/testing/unittest/registar_ut.cpp @@ -275,10 +275,22 @@ Y_UNIT_TEST_SUITE(TUnitTestMacroTest) { } } + std::string ThrowStr() { + if (ThrowMe) { + throw *this; + } + + return {}; + } + void AssertNoException() { UNIT_ASSERT_NO_EXCEPTION(Throw()); } + void AssertNoExceptionRet() { + const TString res = UNIT_ASSERT_NO_EXCEPTION_RESULT(ThrowStr()); + } + template <class TExpectedException> void AssertException() { UNIT_ASSERT_EXCEPTION(Throw(), TExpectedException); @@ -333,6 +345,7 @@ Y_UNIT_TEST_SUITE(TUnitTestMacroTest) { Y_UNIT_TEST(NoException) { UNIT_ASSERT_TEST_FAILS(TTestException().AssertNoException()); + UNIT_ASSERT_TEST_FAILS(TTestException().AssertNoExceptionRet()); UNIT_ASSERT_NO_EXCEPTION(TTestException("", false).Throw()); } |