From a9c9dd4a7df8debbdba12a2a2cd100ab6760d588 Mon Sep 17 00:00:00 2001 From: Alex Hultman Date: Wed, 13 Mar 2019 11:01:23 +0100 Subject: [PATCH] Fix wildcard routing precedence bug, fuzz router --- fuzzing/Http.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++-- src/HttpRouter.h | 24 +++++++++++------------- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/fuzzing/Http.cpp b/fuzzing/Http.cpp index 9603aba..a474f5d 100644 --- a/fuzzing/Http.cpp +++ b/fuzzing/Http.cpp @@ -5,9 +5,48 @@ /* We test the websocket parser */ #include "../src/HttpParser.h" +/* And the router */ +#include "../src/HttpRouter.h" + /* We use this to pad the fuzz */ char *padded = new char[1024 * 500]; +struct StaticData { + + struct RouterData { + + }; + + uWS::HttpRouter router; + + StaticData() { + + router.add("get", "/:hello/:hi", [](RouterData &user, std::pair params) mutable { + + /* This route did handle it */ + return true; + }); + + router.add("post", "/:hello/:hi/*", [](RouterData &user, std::pair params) mutable { + + /* This route did handle it */ + return true; + }); + + router.add("get", "/*", [](RouterData &user, std::pair params) mutable { + + /* This route did not handle it */ + return false; + }); + + router.add("get", "/hi", [](RouterData &user, std::pair params) mutable { + + /* This route did handle it */ + return true; + }); + } +} staticData; + extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Pad the fuzz */ @@ -22,11 +61,17 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* todo: Route this via router */ - httpRequest->getHeader("get"); - httpRequest->getUrl(); + httpRequest->getHeader(httpRequest->getUrl()); httpRequest->getMethod(); httpRequest->getQuery(); + /* Route the method and URL in two passes */ + StaticData::RouterData routerData = {}; + if (!staticData.router.route(httpRequest->getMethod(), httpRequest->getUrl(), routerData)) { + /* It was not handled */ + return nullptr; + } + for (auto p : *httpRequest) { } diff --git a/src/HttpRouter.h b/src/HttpRouter.h index cd0e314..29ea708 100644 --- a/src/HttpRouter.h +++ b/src/HttpRouter.h @@ -79,7 +79,7 @@ private: /* Set URL for router. Will reset any URL cache */ inline void setUrl(std::string_view url) { /* Remove / from input URL */ - currentUrl = url.substr(1); + currentUrl = url.substr(std::min(url.length(), 1)); urlSegmentTop = -1; } @@ -133,7 +133,10 @@ private: /* Wildcard match (can be seen as a shortcut) */ int handlerIndex = p->handler; if (handlerIndex) { - return handlers[handlerIndex](userData, {routeParameters.paramsTop, routeParameters.params}); + int handler = handlers[handlerIndex](userData, {routeParameters.paramsTop, routeParameters.params}); + if (handler) { + return handler; + } } else { /* Unhandled */ return false; @@ -264,21 +267,16 @@ public: routeParameters.reset(); /* Begin by finding the method node */ - Node *parent = &tree; - for (auto &p : parent->children) { + for (auto &p : tree.children) { if (p->name == method) { - parent = p; + /* Then route the url */ + return executeHandlers(p, 0, userData); } } - /* We have that method on record, let's iterate it */ - if (parent != &tree) { - return executeHandlers(parent, 0, userData); - } else { - /* We did not find any handler for this method. - * You may want to re-route with "*" as method. */ - return false; - } + /* We did not find any handler for this method. + * You may want to re-route with "*" as method. */ + return false; } };