aboutsummaryrefslogtreecommitdiff
path: root/src/rest.cpp
diff options
context:
space:
mode:
authorpablomartin4btc <pablomartin4btc@gmail.com>2023-04-14 19:03:08 -0300
committerpablomartin4btc <pablomartin4btc@gmail.com>2023-04-17 10:13:34 -0300
commit11422cc5720c8d73a87600de8fe8abb156db80dc (patch)
tree76363292587e46c2243acbbaa952f93d2ee64714 /src/rest.cpp
parent2bfe43db164de7382d01c06dbdebf250d35f9f2f (diff)
downloadbitcoin-11422cc5720c8d73a87600de8fe8abb156db80dc.tar.xz
bugfix: rest: avoid segfault for invalid URI
`evhttp_uri_parse` can return a nullptr, for example when the URI contains invalid characters (e.g. "%"). `GetQueryParameterFromUri` passes the output of `evhttp_uri_parse` straight into `evhttp_uri_get_query`, which means that anyone calling a REST endpoint in which query parameters are used (e.g. `rest_headers`) can cause a segfault. This bugfix is designed to be minimal and without additional behaviour change. Follow-up work should be done to resolve this in a more general and robust way, so not every endpoint has to handle it individually.
Diffstat (limited to 'src/rest.cpp')
-rw-r--r--src/rest.cpp26
1 files changed, 22 insertions, 4 deletions
diff --git a/src/rest.cpp b/src/rest.cpp
index fa119ddfb7..e46406f1ad 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -200,7 +200,11 @@ static bool rest_headers(const std::any& context,
} else if (path.size() == 1) {
// new path with query parameter: /rest/headers/<hash>?count=<count>
hashStr = path[0];
- raw_count = req->GetQueryParameter("count").value_or("5");
+ try {
+ raw_count = req->GetQueryParameter("count").value_or("5");
+ } catch (const std::runtime_error& e) {
+ return RESTERR(req, HTTP_BAD_REQUEST, e.what());
+ }
} else {
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid URI format. Expected /rest/headers/<hash>.<ext>?count=<count>");
}
@@ -371,7 +375,11 @@ static bool rest_filter_header(const std::any& context, HTTPRequest* req, const
} else if (uri_parts.size() == 2) {
// new path with query parameter: /rest/blockfilterheaders/<filtertype>/<blockhash>?count=<count>
raw_blockhash = uri_parts[1];
- raw_count = req->GetQueryParameter("count").value_or("5");
+ try {
+ raw_count = req->GetQueryParameter("count").value_or("5");
+ } catch (const std::runtime_error& e) {
+ return RESTERR(req, HTTP_BAD_REQUEST, e.what());
+ }
} else {
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid URI format. Expected /rest/blockfilterheaders/<filtertype>/<blockhash>.<ext>?count=<count>");
}
@@ -652,11 +660,21 @@ static bool rest_mempool(const std::any& context, HTTPRequest* req, const std::s
case RESTResponseFormat::JSON: {
std::string str_json;
if (param == "contents") {
- const std::string raw_verbose{req->GetQueryParameter("verbose").value_or("true")};
+ std::string raw_verbose;
+ try {
+ raw_verbose = req->GetQueryParameter("verbose").value_or("true");
+ } catch (const std::runtime_error& e) {
+ return RESTERR(req, HTTP_BAD_REQUEST, e.what());
+ }
if (raw_verbose != "true" && raw_verbose != "false") {
return RESTERR(req, HTTP_BAD_REQUEST, "The \"verbose\" query parameter must be either \"true\" or \"false\".");
}
- const std::string raw_mempool_sequence{req->GetQueryParameter("mempool_sequence").value_or("false")};
+ std::string raw_mempool_sequence;
+ try {
+ raw_mempool_sequence = req->GetQueryParameter("mempool_sequence").value_or("false");
+ } catch (const std::runtime_error& e) {
+ return RESTERR(req, HTTP_BAD_REQUEST, e.what());
+ }
if (raw_mempool_sequence != "true" && raw_mempool_sequence != "false") {
return RESTERR(req, HTTP_BAD_REQUEST, "The \"mempool_sequence\" query parameter must be either \"true\" or \"false\".");
}