diff --git a/libs/linglong/tests/ll-tests/src/linglong/utils/io_test.cpp b/libs/linglong/tests/ll-tests/src/linglong/utils/io_test.cpp index 3e3216e4e..e1ae59c14 100644 --- a/libs/linglong/tests/ll-tests/src/linglong/utils/io_test.cpp +++ b/libs/linglong/tests/ll-tests/src/linglong/utils/io_test.cpp @@ -15,6 +15,8 @@ #include "linglong/utils/unique_fd.h" #include +#include +#include #include #include @@ -259,6 +261,14 @@ TEST(RingBuffer, ClearResetsState) EXPECT_EQ(buf->size(), 0); } +TEST(RingBuffer, CreateRejectsOversizedCapacity) +{ + // A power-of-two capacity beyond vector::max_size() must be reported via + // the empty optional instead of escaping the noexcept boundary. + auto oversized = std::size_t{ 1 } << (sizeof(std::size_t) * CHAR_BIT - 1); + EXPECT_FALSE(RingBuffer::create(oversized).has_value()); +} + TEST(EventLoop, CreateAndWaitTimeout) { auto loop = EventLoop::create(); diff --git a/libs/utils/src/linglong/utils/io/ring_buffer.h b/libs/utils/src/linglong/utils/io/ring_buffer.h index 95c265aae..2d2113086 100644 --- a/libs/utils/src/linglong/utils/io/ring_buffer.h +++ b/libs/utils/src/linglong/utils/io/ring_buffer.h @@ -31,8 +31,16 @@ class alignas(hardware_constructive_interference_size) RingBuffer return std::nullopt; } - std::vector data(cap); - return RingBuffer{ std::move(data), cap - 1 }; + if (cap > std::vector().max_size()) { + return std::nullopt; + } + + try { + std::vector data(cap); + return RingBuffer{ std::move(data), cap - 1 }; + } catch (...) { + return std::nullopt; + } } RingBuffer(const RingBuffer &) = delete;