Commit 5a5655b7 authored by Max Kellermann's avatar Max Kellermann

lib/curl/Adapter: catch and postpone exceptions in WriteFunction()

This fixes a std::terminate() crash in the CURL storage plugin when PropfindOperation::OnHeaders() throws an exception after receiving a non-207 status. Closes https://github.com/MusicPlayerDaemon/MPD/issues/1559
parent b88d1e68
ver 0.23.8 (not yet released)
* storage
- curl: fix crash if web server does not understand WebDAV
ver 0.23.7 (2022/05/09)
* database
......
......@@ -85,6 +85,12 @@ CurlResponseHandlerAdapter::FinishBody()
void
CurlResponseHandlerAdapter::Done(CURLcode result) noexcept
{
if (postponed_error) {
state = State::CLOSED;
handler.OnError(std::move(postponed_error));
return;
}
try {
if (result != CURLE_OK) {
StripRight(error_buffer);
......@@ -172,6 +178,13 @@ CurlResponseHandlerAdapter::DataReceived(const void *ptr,
return received_size;
} catch (CurlResponseHandler::Pause) {
return CURL_WRITEFUNC_PAUSE;
} catch (...) {
/* from inside this libCURL callback function, we
can't do much, so we remember the exception to be
handled later by Done(), and return 0, causing the
response to be aborted with CURLE_WRITE_ERROR */
postponed_error = std::current_exception();
return 0;
}
}
......
......@@ -34,6 +34,7 @@
#include <curl/curl.h>
#include <cstddef>
#include <exception>
struct StringView;
class CurlEasy;
......@@ -46,6 +47,12 @@ class CurlResponseHandlerAdapter {
Curl::Headers headers;
/**
* An exception caught from within the WriteFunction() which
* will later be handled by Done().
*/
std::exception_ptr postponed_error;
/** error message provided by libcurl */
char error_buffer[CURL_ERROR_SIZE];
......
......@@ -50,13 +50,19 @@ public:
/**
* Status line and headers have been received.
*
* Exceptions thrown by this method will be passed to
* OnError(), aborting the request.
*/
virtual void OnHeaders(unsigned status, Curl::Headers &&headers) = 0;
/**
* Response body data has been received.
*
* May throw #Pause (but nothing else).
* May throw #Pause.
*
* Other exceptions thrown by this method will be passed to
* OnError(), aborting the request.
*/
virtual void OnData(ConstBuffer<void> data) = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment