Skip to content

Commit a087e5c

Browse files
committed
bug#27732224 Fix deadlock when sending > max_packet size.
1 parent b7842b1 commit a087e5c

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

cdk/foundation/connection_openssl.cc

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,43 @@ static void throw_openssl_error()
118118
throw_openssl_error_msg(buffer);
119119
}
120120

121+
/*
122+
Function should be called after SSL_read/SSL_write returns error (<=0).
123+
It will get ssl error and throw it if needed.
124+
Will return normally if the error can be continued.
125+
*/
126+
static void throw_ssl_error(SSL* tls, int err)
127+
{
128+
switch(SSL_get_error(tls, err))
129+
{
130+
case SSL_ERROR_WANT_READ:
131+
case SSL_ERROR_WANT_WRITE:
132+
#ifndef WITH_SSL_YASSL
133+
case SSL_ERROR_WANT_CONNECT:
134+
case SSL_ERROR_WANT_ACCEPT:
135+
case SSL_ERROR_WANT_X509_LOOKUP:
136+
# if OPENSSL_VERSION_NUMBER >= 0x10100000L
137+
case SSL_ERROR_WANT_ASYNC:
138+
case SSL_ERROR_WANT_ASYNC_JOB:
139+
# endif
140+
#endif
141+
//Will not throw anything, so function that calls this, will continue.
142+
break;
143+
case SSL_ERROR_ZERO_RETURN:
144+
throw cdk::foundation::connection::Error_eos();
145+
case SSL_ERROR_SYSCALL:
146+
cdk::foundation::throw_posix_error();
147+
case SSL_ERROR_SSL:
148+
throw_openssl_error();
149+
default:
150+
{
151+
char buffer[512];
152+
ERR_error_string_n(static_cast<unsigned long>(SSL_get_error(tls, err)), buffer, sizeof(buffer));
153+
throw_openssl_error_msg(buffer);
154+
}
155+
}
156+
}
157+
121158

122159
/*
123160
Implementation of TLS connection class.
@@ -467,8 +504,10 @@ bool TLS::Read_op::common_read()
467504

468505
int result = SSL_read(impl.m_tls, data, buffer_size);
469506

470-
if (result == -1)
471-
throw IO_error(SSL_get_error(impl.m_tls,0));
507+
if (result <= 0)
508+
{
509+
throw_ssl_error(impl.m_tls, result);
510+
}
472511

473512
if (result > 0)
474513
{
@@ -525,6 +564,11 @@ bool TLS::Read_some_op::common_read()
525564

526565
int result = SSL_read(impl.m_tls, buffer.begin(), (int)buffer.size());
527566

567+
if (result <= 0)
568+
{
569+
throw_ssl_error(impl.m_tls, result);
570+
}
571+
528572
if (result > 0)
529573
{
530574
set_completed(static_cast<size_t>(result));
@@ -574,6 +618,11 @@ bool TLS::Write_op::common_write()
574618

575619
int result = SSL_write(impl.m_tls, data, buffer_size);
576620

621+
if (result <= 0)
622+
{
623+
throw_ssl_error(impl.m_tls, result);
624+
}
625+
577626
if (result > 0)
578627
{
579628
m_currentBufferOffset += result;
@@ -629,6 +678,11 @@ bool TLS::Write_some_op::common_write()
629678

630679
int result = SSL_write(impl.m_tls, buffer.begin(), (int)buffer.size());
631680

681+
if (result <= 0)
682+
{
683+
throw_ssl_error(impl.m_tls, result);
684+
}
685+
632686
if (result > 0)
633687
{
634688
set_completed(static_cast<size_t>(result));

devapi/tests/bugs-t.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ TEST_F(Bugs, bug26130226_crash_update)
118118

119119
TEST_F(Bugs, bug_26962725_double_bind)
120120
{
121+
SKIP_IF_NO_XPLUGIN;
122+
121123
get_sess().dropSchema("bug_26962725_double_bind");
122124
Schema db = get_sess().createSchema("bug_26962725_double_bind");
123125
/// Collection.find() function with fixed values
@@ -258,3 +260,31 @@ TEST_F(Bugs, bug_27727505_multiple_results)
258260
}
259261

260262

263+
TEST_F(Bugs, bug_hang_send_maxpacket)
264+
{
265+
SKIP_IF_NO_XPLUGIN;
266+
267+
auto schema = get_sess().createSchema("bug_hang_maxpacket",true);
268+
schema.dropCollection("test");
269+
auto coll = schema.createCollection("max_packet",true);
270+
271+
auto query_max_packet = sql("show variables like '%mysqlx_max_allowed_packet%'");
272+
273+
size_t maxpacket = std::stoul(query_max_packet.fetchOne()[1].get<std::string>());
274+
275+
std::string name(maxpacket,L'A');
276+
277+
std::stringstream buffer;
278+
buffer << R"({ "name": ")" << name << R"("})";
279+
280+
try{
281+
coll.add(buffer.str()).execute();
282+
FAIL() << "Should have thrown error!";
283+
}
284+
catch (Error &e)
285+
{
286+
std::cout << "Expected: " << e << std::endl;
287+
}
288+
289+
}
290+

0 commit comments

Comments
 (0)