Skip to content

Commit 387b3c6

Browse files
authored
Prevent use of regex in http_endpoint outside of registration
* Prevent use of regex in http_endpoint outside of registration. This avoids an abort whenever an invalid regex is passed as a URL in an http request. * No need to throw new
1 parent bd6b202 commit 387b3c6

File tree

5 files changed

+71
-16
lines changed

5 files changed

+71
-16
lines changed

src/details/http_endpoint.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
USA
1919
*/
2020

21+
#include <stdexcept>
22+
2123
#include "httpserver/details/http_endpoint.hpp"
2224

2325
#include "httpserver/http_utils.hpp"
@@ -47,6 +49,11 @@ http_endpoint::http_endpoint
4749
family_url(family),
4850
reg_compiled(false)
4951
{
52+
if (use_regex && !registration)
53+
{
54+
throw std::invalid_argument("Cannot use regex if not during registration");
55+
}
56+
5057
url_normalized = use_regex ? "^/" : "/";
5158
vector<string> parts;
5259

@@ -115,7 +122,14 @@ http_endpoint::http_endpoint
115122
if(use_regex)
116123
{
117124
url_normalized += "$";
118-
re_url_normalized = std::regex(url_normalized, std::regex::extended | std::regex::icase | std::regex::nosubs);
125+
try
126+
{
127+
re_url_normalized = std::regex(url_normalized, std::regex::extended | std::regex::icase | std::regex::nosubs);
128+
}
129+
catch (std::regex_error& e)
130+
{
131+
throw std::invalid_argument("Not a valid regex in URL: " + url_normalized);
132+
}
119133
reg_compiled = true;
120134
}
121135
}
@@ -126,9 +140,9 @@ http_endpoint::http_endpoint(const http_endpoint& h):
126140
url_pars(h.url_pars),
127141
url_pieces(h.url_pieces),
128142
chunk_positions(h.chunk_positions),
143+
re_url_normalized(h.re_url_normalized),
129144
family_url(h.family_url),
130-
reg_compiled(h.reg_compiled),
131-
re_url_normalized(h.re_url_normalized)
145+
reg_compiled(h.reg_compiled)
132146
{
133147
}
134148

src/httpserver/details/http_endpoint.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class http_endpoint
156156
http_endpoint(const std::string& url,
157157
bool family = false,
158158
bool registration = false,
159-
bool use_regex = true
159+
bool use_regex = false
160160
);
161161
private:
162162
/**

src/webserver.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ bool webserver::stop()
378378

379379
void webserver::unregister_resource(const string& resource)
380380
{
381-
details::http_endpoint he(resource);
381+
// family does not matter - it just checks the url_normalized anyhow
382+
details::http_endpoint he(resource, false, true, regex_checking);
382383
registered_resources.erase(he);
383384
registered_resources.erase(he.get_url_complete());
384385
registered_resources_str.erase(he.get_url_complete());
@@ -621,7 +622,7 @@ int webserver::finalize_answer(
621622

622623
map<details::http_endpoint, http_resource*>::iterator found_endpoint;
623624

624-
details::http_endpoint endpoint(st_url, false, false, regex_checking);
625+
details::http_endpoint endpoint(st_url, false, false, false);
625626

626627
map<details::http_endpoint, http_resource*>::iterator it;
627628

test/integ/basic.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,24 @@ LT_BEGIN_AUTO_TEST(basic_suite, long_path_pieces)
993993
curl_easy_cleanup(curl);
994994
LT_END_AUTO_TEST(long_path_pieces)
995995

996+
LT_BEGIN_AUTO_TEST(basic_suite, url_with_regex_like_pieces)
997+
path_pieces_resource resource;
998+
ws->register_resource("/settings", &resource, true);
999+
curl_global_init(CURL_GLOBAL_ALL);
1000+
1001+
std::string s;
1002+
CURL *curl = curl_easy_init();
1003+
CURLcode res;
1004+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:8080/settings/{}");
1005+
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
1006+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
1007+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
1008+
res = curl_easy_perform(curl);
1009+
LT_ASSERT_EQ(res, 0);
1010+
LT_CHECK_EQ(s, "settings,{},");
1011+
curl_easy_cleanup(curl);
1012+
LT_END_AUTO_TEST(url_with_regex_like_pieces)
1013+
9961014
LT_BEGIN_AUTO_TEST_ENV()
9971015
AUTORUN_TESTS()
9981016
LT_END_AUTO_TEST_ENV()

test/unit/http_endpoint_test.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_default)
5050
LT_CHECK_EQ(test_endpoint.is_regex_compiled(), false);
5151
LT_END_AUTO_TEST(http_endpoint_default)
5252

53-
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_default)
54-
http_endpoint test_endpoint("/path/to/resource");
53+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_registration)
54+
http_endpoint test_endpoint("/path/to/resource", false, true, true);
5555

5656
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
5757
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource$");
@@ -66,10 +66,10 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_default)
6666

6767
LT_CHECK_EQ(test_endpoint.is_family_url(), false);
6868
LT_CHECK_EQ(test_endpoint.is_regex_compiled(), true);
69-
LT_END_AUTO_TEST(http_endpoint_from_string_default)
69+
LT_END_AUTO_TEST(http_endpoint_from_string_registration)
7070

7171
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_not_beginning_with_slash)
72-
http_endpoint test_endpoint("path/to/resource");
72+
http_endpoint test_endpoint("path/to/resource", false, true, true);
7373

7474
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
7575
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource$");
@@ -87,7 +87,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_not_beginning_
8787
LT_END_AUTO_TEST(http_endpoint_from_string_not_beginning_with_slash)
8888

8989
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_ending_with_slash)
90-
http_endpoint test_endpoint("path/to/resource/");
90+
http_endpoint test_endpoint("path/to/resource/", false, true, true);
9191

9292
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
9393
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource$");
@@ -105,7 +105,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_ending_with_sl
105105
LT_END_AUTO_TEST(http_endpoint_from_string_ending_with_slash)
106106

107107
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_family)
108-
http_endpoint test_endpoint("/path/to/resource", true);
108+
http_endpoint test_endpoint("/path/to/resource", true, true, true);
109109

110110
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
111111
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource$");
@@ -122,6 +122,24 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_family)
122122
LT_CHECK_EQ(test_endpoint.is_regex_compiled(), true);
123123
LT_END_AUTO_TEST(http_endpoint_from_string_family)
124124

125+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_default_no_regex)
126+
http_endpoint test_endpoint("/path/to/resource");
127+
128+
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
129+
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "/path/to/resource");
130+
131+
LT_CHECK_EQ(test_endpoint.get_url_pars().size(), 0);
132+
133+
string expected_arr[] = { "path", "to", "resource" };
134+
vector<string> expected_pieces(expected_arr, expected_arr + sizeof(expected_arr) / sizeof(expected_arr[0]));
135+
LT_CHECK_COLLECTIONS_EQ(test_endpoint.get_url_pieces().begin(), test_endpoint.get_url_pieces().end(), expected_pieces.begin());
136+
137+
LT_CHECK_EQ(test_endpoint.get_chunk_positions().size(), 0);
138+
139+
LT_CHECK_EQ(test_endpoint.is_family_url(), false);
140+
LT_CHECK_EQ(test_endpoint.is_regex_compiled(), false);
141+
LT_END_AUTO_TEST(http_endpoint_default_no_regex)
142+
125143
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_no_regex)
126144
http_endpoint test_endpoint("/path/to/resource", false, false, false);
127145

@@ -141,7 +159,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_no_regex)
141159
LT_END_AUTO_TEST(http_endpoint_from_string_no_regex)
142160

143161
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration)
144-
http_endpoint test_endpoint("/path/to/resource", false, true);
162+
http_endpoint test_endpoint("/path/to/resource", false, true, true);
145163

146164
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
147165
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource$");
@@ -159,7 +177,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration)
159177
LT_END_AUTO_TEST(http_endpoint_registration)
160178

161179
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_nested_regex)
162-
http_endpoint test_endpoint("/path/to/resource/with/[0-9]+/to/fetch", false, true);
180+
http_endpoint test_endpoint("/path/to/resource/with/[0-9]+/to/fetch", false, true, true);
163181

164182
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource/with/[0-9]+/to/fetch");
165183
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource/with/[0-9]+/to/fetch$");
@@ -177,7 +195,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_nested_regex)
177195
LT_END_AUTO_TEST(http_endpoint_registration_nested_regex)
178196

179197
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_arg)
180-
http_endpoint test_endpoint("/path/to/resource/with/{arg}/to/fetch", false, true);
198+
http_endpoint test_endpoint("/path/to/resource/with/{arg}/to/fetch", false, true, true);
181199

182200
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource/with/{arg}/to/fetch");
183201
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource/with/([^\\/]+)/to/fetch$");
@@ -199,7 +217,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_arg)
199217
LT_END_AUTO_TEST(http_endpoint_registration_arg)
200218
201219
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_arg_custom_regex)
202-
http_endpoint test_endpoint("/path/to/resource/with/{arg|([0-9]+)}/to/fetch", false, true);
220+
http_endpoint test_endpoint("/path/to/resource/with/{arg|([0-9]+)}/to/fetch", false, true, true);
203221
204222
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource/with/{arg|([0-9]+)}/to/fetch");
205223
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource/with/([0-9]+)/to/fetch$");
@@ -318,6 +336,10 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_match_regex_disabled)
318336
LT_CHECK_THROW(test_endpoint.match(http_endpoint("/path/to/resource")));
319337
LT_END_AUTO_TEST(http_endpoint_match_regex_disabled)
320338
339+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_cannot_use_regex_if_not_registering)
340+
LT_CHECK_THROW(http_endpoint("/path/to/resource", false, false, true));
341+
LT_END_AUTO_TEST(http_endpoint_cannot_use_regex_if_not_registering)
342+
321343
LT_BEGIN_AUTO_TEST(http_endpoint_suite, comparator)
322344
LT_CHECK_EQ(http_endpoint("/a/b") < http_endpoint("/a/c"), true);
323345
LT_CHECK_EQ(http_endpoint("/a/c") < http_endpoint("/a/b"), false);

0 commit comments

Comments
 (0)