From 830750edd49d9fe5219ff2f581afdfec63e93c56 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 9 Apr 2022 09:04:37 +0900 Subject: [PATCH] feat: throws exception when controller name in routes contains `/` --- system/Language/en/Router.php | 1 + system/Router/Exceptions/RouterException.php | 10 ++++++++++ system/Router/Router.php | 5 +++++ tests/system/Router/RouterTest.php | 12 ++++++++++++ 4 files changed, 28 insertions(+) diff --git a/system/Language/en/Router.php b/system/Language/en/Router.php index 90aaa132b4..7d0b5cc99e 100644 --- a/system/Language/en/Router.php +++ b/system/Language/en/Router.php @@ -14,4 +14,5 @@ return [ 'invalidParameter' => 'A parameter does not match the expected type.', 'missingDefaultRoute' => 'Unable to determine what should be displayed. A default route has not been specified in the routing file.', 'invalidDynamicController' => 'A dynamic controller is not allowed for security reasons. Route handler: {0}', + 'invalidControllerName' => 'The namespace delimiter is a backslash (\), not a slash (/). Route handler: {0}', ]; diff --git a/system/Router/Exceptions/RouterException.php b/system/Router/Exceptions/RouterException.php index b50042b342..5a510e4716 100644 --- a/system/Router/Exceptions/RouterException.php +++ b/system/Router/Exceptions/RouterException.php @@ -68,4 +68,14 @@ class RouterException extends FrameworkException { return new static(lang('Router.invalidDynamicController', [$handler])); } + + /** + * Throw when controller name has `/`. + * + * @return RouterException + */ + public static function forInvalidControllerName(string $handler) + { + return new static(lang('Router.invalidControllerName', [$handler])); + } } diff --git a/system/Router/Router.php b/system/Router/Router.php index 42f2eb0c7a..37c8811417 100644 --- a/system/Router/Router.php +++ b/system/Router/Router.php @@ -426,6 +426,11 @@ class Router implements RouterInterface throw RouterException::forDynamicController($handler); } + // Checks `/` in controller name + if (strpos($controller, '/') !== false) { + throw RouterException::forInvalidControllerName($handler); + } + if (strpos($routeKey, '/') !== false) { $replacekey = str_replace('/(.*)', '', $routeKey); $handler = preg_replace('#^' . $routeKey . '$#u', $handler, $uri); diff --git a/tests/system/Router/RouterTest.php b/tests/system/Router/RouterTest.php index d3ca04422c..38eb9b7ba4 100644 --- a/tests/system/Router/RouterTest.php +++ b/tests/system/Router/RouterTest.php @@ -61,6 +61,7 @@ final class RouterTest extends CIUnitTestCase 'closure/(:num)/(:alpha)' => static fn ($num, $str) => $num . '-' . $str, '{locale}/pages' => 'App\Pages::list_all', 'admin/admins' => 'App\Admin\Admins::list_all', + 'admin/admins/edit/(:any)' => 'App/Admin/Admins::edit_show/$1', '/some/slash' => 'App\Slash::index', 'objects/(:segment)/sort/(:segment)/([A-Z]{3,7})' => 'AdminList::objectsSortCreate/$1/$2/$3', '(:segment)/(:segment)/(:segment)' => '$2::$3/$1', @@ -402,6 +403,17 @@ final class RouterTest extends CIUnitTestCase $this->assertSame('list_all', $router->methodName()); } + public function testRouteWithSlashInControllerName() + { + $this->expectExceptionMessage( + 'The namespace delimiter is a backslash (\), not a slash (/). Route handler: \App/Admin/Admins::edit_show/$1' + ); + + $router = new Router($this->collection, $this->request); + + $router->handle('admin/admins/edit/1'); + } + public function testRouteWithLeadingSlash() { $router = new Router($this->collection, $this->request);