diff --git a/src/core/test/CMakeLists.txt b/src/core/test/CMakeLists.txt index 5207c767d..784c1b543 100644 --- a/src/core/test/CMakeLists.txt +++ b/src/core/test/CMakeLists.txt @@ -1,6 +1,6 @@ if (BUILD_TESTING AND (GTest_FOUND OR GTEST_FOUND)) - add_executable(core_test pack_test.cpp events_test.cpp chain_test.cpp) - target_link_libraries(core_test PRIVATE GTest::gtest_main core GTest::gtest) + add_executable(core_test pack_test.cpp events_test.cpp chain_test.cpp packet_test.cpp) + target_link_libraries(core_test PRIVATE GTest::gtest_main core c2pool_merged_mining GTest::gtest) include(GoogleTest) include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) diff --git a/src/core/test/packet_test.cpp b/src/core/test/packet_test.cpp new file mode 100644 index 000000000..5b5e5f6d6 --- /dev/null +++ b/src/core/test/packet_test.cpp @@ -0,0 +1,64 @@ +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// A4 (Bug-9 hardening) cap-boundary tests for the Packet read-constructor. +// The read ctor caps prefix_length at MAX_PREFIX_LENGTH (16) and throws +// std::ios_base::failure on over-cap values, which is how UAF garbage from a +// destroyed m_node (Bug-3-family rapid disconnect/reconnect) is rejected +// without crashing the process. See src/core/packet.hpp. +namespace { + +constexpr size_t kCap = 16; // must track MAX_PREFIX_LENGTH in packet.hpp + +// --- at/under the cap: must succeed and size the prefix exactly --- + +TEST(PacketPrefixCap, ZeroLengthSucceeds) +{ + core::Packet p(0); + EXPECT_EQ(p.prefix.size(), 0u); +} + +TEST(PacketPrefixCap, JustUnderCapSucceeds) +{ + core::Packet p(kCap - 1); + EXPECT_EQ(p.prefix.size(), kCap - 1); +} + +TEST(PacketPrefixCap, AtCapSucceeds) +{ + // Boundary: exactly at the cap is the largest accepted value. + core::Packet p(kCap); + EXPECT_EQ(p.prefix.size(), kCap); +} + +// --- over the cap: must throw cleanly, never resize --- + +TEST(PacketPrefixCap, JustOverCapThrows) +{ + EXPECT_THROW({ core::Packet p(kCap + 1); }, std::ios_base::failure); +} + +TEST(PacketPrefixCap, WayOverCapThrows) +{ + EXPECT_THROW({ core::Packet p(1024); }, std::ios_base::failure); +} + +TEST(PacketPrefixCap, UafGarbageMaxSizeThrows) +{ + // Simulates the garbage size_t read from a freed m_node vector; pre-cap + // this reached resize() and aborted via std::length_error. + EXPECT_THROW({ core::Packet p(std::numeric_limits::max()); }, + std::ios_base::failure); +} + +} // namespace