diff --git a/hazelcast/include/hazelcast/client/internal/socket/BaseSocket.h b/hazelcast/include/hazelcast/client/internal/socket/BaseSocket.h index ecc7184fb..bd8392358 100644 --- a/hazelcast/include/hazelcast/client/internal/socket/BaseSocket.h +++ b/hazelcast/include/hazelcast/client/internal/socket/BaseSocket.h @@ -19,7 +19,15 @@ #include #include #ifdef HZ_BUILD_WITH_SSL -#include +// Avoid because in Boost <= 1.83 it transitively +// includes rfc2818_verification, whose .ipp dereferences private +// ASN1_STRING fields that became opaque in OpenSSL 3.x and breaks the +// MSVC build. We use the modern host_name_verification instead, so pull +// in only the specific subheaders we actually need. +#include +#include +#include +#include #endif #include "hazelcast/client/socket.h" diff --git a/hazelcast/include/hazelcast/client/internal/socket/SSLSocket.h b/hazelcast/include/hazelcast/client/internal/socket/SSLSocket.h index 2051b299e..77079587a 100644 --- a/hazelcast/include/hazelcast/client/internal/socket/SSLSocket.h +++ b/hazelcast/include/hazelcast/client/internal/socket/SSLSocket.h @@ -18,7 +18,13 @@ #ifdef HZ_BUILD_WITH_SSL #include -#include +// See BaseSocket.h: in Boost <= 1.83 transitively +// pulls in rfc2818_verification, which fails to compile against +// OpenSSL 3.x (opaque ASN1_STRING). Use specific subheaders instead. +#include +#include +#include +#include #include "hazelcast/client/internal/socket/BaseSocket.h" diff --git a/hazelcast/include/hazelcast/client/internal/socket/SocketFactory.h b/hazelcast/include/hazelcast/client/internal/socket/SocketFactory.h index 0e1fc07e9..5d04b1f7e 100644 --- a/hazelcast/include/hazelcast/client/internal/socket/SocketFactory.h +++ b/hazelcast/include/hazelcast/client/internal/socket/SocketFactory.h @@ -22,7 +22,13 @@ #ifdef HZ_BUILD_WITH_SSL #include -#include +// See BaseSocket.h: in Boost <= 1.83 transitively +// pulls in rfc2818_verification, which fails to compile against +// OpenSSL 3.x (opaque ASN1_STRING). Use specific subheaders instead. +#include +#include +#include +#include #endif // HZ_BUILD_WITH_SSL diff --git a/hazelcast/test/src/sql_test.cpp b/hazelcast/test/src/sql_test.cpp index 36585c616..ebb14bf0e 100644 --- a/hazelcast/test/src/sql_test.cpp +++ b/hazelcast/test/src/sql_test.cpp @@ -1870,8 +1870,34 @@ TEST_F(SqlTest, select) std::unordered_set unique_keys; - for (auto itr = res->iterator(); itr.has_next();) { - auto page = itr.next().get(); + // Fetch the first page up front so we can verify the bounds-checking API + // on a single representative row before the main loop. + // Background: on Windows, C++ exceptions are built on SEH. When ProcDump + // is attached as a debugger (CI step: procdump -e -ma -w client_test.exe), + // every throw raises SEH code 0xE06D7363, which the OS delivers as a + // first-chance debug event to ProcDump before the C++ catch handler runs. + // ProcDump logs the line "[HH:MM:SS]Exception: E06D7363.?AV..." and then + // calls ContinueDebugEvent so execution can proceed. This is a mandatory + // two-kernel-mode-transition round-trip for every single throw. + // With the EXPECT_THROW calls inside the 4096-row loop that is ~12 000 + // round-trips, stalling the loop long enough to trigger connection + // timeouts on the server side (Windows-only flaky failure). + auto itr = res->iterator(); + ASSERT_TRUE(itr.has_next()); + auto page = itr.next().get(); + ASSERT_FALSE(page->rows().empty()); + { + const auto& first_row = page->rows().front(); + EXPECT_THROW(first_row.get_object(-1), + exception::index_out_of_bounds); + EXPECT_THROW( + first_row.get_object(first_row.row_metadata().column_count()), + exception::index_out_of_bounds); + EXPECT_THROW(first_row.get_object("unknown_field"), + exception::illegal_argument); + } + + for (;;) { for (const auto& row : page->rows()) { ASSERT_EQ(row_metadata, res->row_metadata()); @@ -1903,14 +1929,10 @@ TEST_F(SqlTest, select) sql_column_type::varchar, val.varchar_val, row, "varcharVal"); unique_keys.emplace(*key0); - - EXPECT_THROW(row.get_object(-1), - exception::index_out_of_bounds); - EXPECT_THROW(row.get_object(row.row_metadata().column_count()), - exception::index_out_of_bounds); - EXPECT_THROW(row.get_object("unknown_field"), - exception::illegal_argument); } + if (!itr.has_next()) + break; + page = itr.next().get(); } EXPECT_THROW(res->iterator(), exception::illegal_state);