Skip to content

Commit be5d43f

Browse files
renemeBillyONeal
authored andcommitted
FIX: crash with std::logic_error when reusing a connection that timed out on the server (#1019)
* FIX: check whether instream() is valid before trying to rewind * add .can_seek() as a second line of defense * apply clang-format * improve error reporting for unrewindable streams * Add René Meusel (reneme) to CONTRIBUTORS.txt.
1 parent 21a609b commit be5d43f

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

CONTRIBUTORS.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@ Christian Deneke (chris0x44)
5353
leetal
5454

5555
Benjamin Lee (mobileben)
56+
René Meusel (reneme)

Release/src/http/client/http_client_asio.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,39 @@ class asio_context final : public request_context, public std::enable_shared_fro
13221322
// cancellation registration to maintain the old state.
13231323
// This also obtains a new connection from pool.
13241324
auto new_ctx = create_request_context(m_http_client, m_request);
1325-
new_ctx->m_request._get_impl()->instream().seek(0);
1325+
1326+
// If the request contains a valid instream, we try to rewind it to
1327+
// replay the just-failed request. Otherwise we assume that no data
1328+
// was sent in the first place.
1329+
const auto& instream = new_ctx->m_request._get_impl()->instream();
1330+
if (instream)
1331+
{
1332+
// As stated in the commit message of f4f2348, we might encounter
1333+
// streams that are not capable of rewinding and hence resending the
1334+
// request is not possible. We cannot recover from this condition and
1335+
// need to escalate it to the using code.
1336+
if (!instream.can_seek())
1337+
{
1338+
report_error("cannot rewind input stream for connection re-establishment",
1339+
ec,
1340+
httpclient_errorcode_context::readheader);
1341+
return;
1342+
}
1343+
1344+
try
1345+
{
1346+
// Rewinding the stream might throw, in which case we cannot do the
1347+
// connection re-establishment transparently. I.e. report the exception
1348+
// to the calling code.
1349+
instream.seek(0);
1350+
}
1351+
catch (...)
1352+
{
1353+
report_exception(std::current_exception());
1354+
return;
1355+
}
1356+
}
1357+
13261358
new_ctx->m_request_completion = m_request_completion;
13271359
new_ctx->m_cancellationRegistration = m_cancellationRegistration;
13281360

0 commit comments

Comments
 (0)