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
This commit is contained in:
parent
b88d1e6820
commit
5a5655b790
2
NEWS
2
NEWS
|
@ -1,4 +1,6 @@
|
||||||
ver 0.23.8 (not yet released)
|
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)
|
ver 0.23.7 (2022/05/09)
|
||||||
* database
|
* database
|
||||||
|
|
|
@ -85,6 +85,12 @@ CurlResponseHandlerAdapter::FinishBody()
|
||||||
void
|
void
|
||||||
CurlResponseHandlerAdapter::Done(CURLcode result) noexcept
|
CurlResponseHandlerAdapter::Done(CURLcode result) noexcept
|
||||||
{
|
{
|
||||||
|
if (postponed_error) {
|
||||||
|
state = State::CLOSED;
|
||||||
|
handler.OnError(std::move(postponed_error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (result != CURLE_OK) {
|
if (result != CURLE_OK) {
|
||||||
StripRight(error_buffer);
|
StripRight(error_buffer);
|
||||||
|
@ -172,6 +178,13 @@ CurlResponseHandlerAdapter::DataReceived(const void *ptr,
|
||||||
return received_size;
|
return received_size;
|
||||||
} catch (CurlResponseHandler::Pause) {
|
} catch (CurlResponseHandler::Pause) {
|
||||||
return CURL_WRITEFUNC_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 <curl/curl.h>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
struct StringView;
|
struct StringView;
|
||||||
class CurlEasy;
|
class CurlEasy;
|
||||||
|
@ -46,6 +47,12 @@ class CurlResponseHandlerAdapter {
|
||||||
|
|
||||||
Curl::Headers headers;
|
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 */
|
/** error message provided by libcurl */
|
||||||
char error_buffer[CURL_ERROR_SIZE];
|
char error_buffer[CURL_ERROR_SIZE];
|
||||||
|
|
||||||
|
|
|
@ -50,13 +50,19 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status line and headers have been received.
|
* 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;
|
virtual void OnHeaders(unsigned status, Curl::Headers &&headers) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response body data has been received.
|
* 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;
|
virtual void OnData(ConstBuffer<void> data) = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue