summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2017-02-13 15:47:12 +0000
committerAlex Pott2017-02-13 15:47:12 +0000
commit39d1e8557f8b0c7748b1fb151292c166e4cf7133 (patch)
tree2342600523052cb5a6f805f4126827c3daa4a644
parentd313bdda9467121455c2f4088ac00698fa503017 (diff)
Issue #2822190 by webflo, Wim Leers, dawehner, alexpott, effulgentsia, SchnWalter: PathValidator validates based on a RequestContext leaked from the current request, resulting in false negatives during CLI requests and POST submissions
-rw-r--r--core/lib/Drupal/Core/Path/PathValidator.php18
-rw-r--r--core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php68
2 files changed, 81 insertions, 5 deletions
diff --git a/core/lib/Drupal/Core/Path/PathValidator.php b/core/lib/Drupal/Core/Path/PathValidator.php
index f7efdb1..efce473 100644
--- a/core/lib/Drupal/Core/Path/PathValidator.php
+++ b/core/lib/Drupal/Core/Path/PathValidator.php
@@ -6,6 +6,7 @@ use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\ParamConverter\ParamNotConvertedException;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\Routing\AccessAwareRouterInterface;
+use Drupal\Core\Routing\RequestContext;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
@@ -152,23 +153,30 @@ class PathValidator implements PathValidatorInterface {
$router = $this->accessAwareRouter;
}
+ $initial_request_context = $router->getContext() ? $router->getContext() : new RequestContext();
$path = $this->pathProcessor->processInbound('/' . $path, $request);
try {
- return $router->match($path);
+ $request_context = new RequestContext();
+ $request_context->fromRequest($request);
+ $router->setContext($request_context);
+ $result = $router->match($path);
}
catch (ResourceNotFoundException $e) {
- return FALSE;
+ $result = FALSE;
}
catch (ParamNotConvertedException $e) {
- return FALSE;
+ $result = FALSE;
}
catch (AccessDeniedHttpException $e) {
- return FALSE;
+ $result = FALSE;
}
catch (MethodNotAllowedException $e) {
- return FALSE;
+ $result = FALSE;
}
+
+ $router->setContext($initial_request_context);
+ return $result;
}
}
diff --git a/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php b/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php
new file mode 100644
index 0000000..3463dce
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace Drupal\KernelTests\Core\Path;
+
+use Drupal\Core\Routing\RequestContext;
+use Drupal\Core\Url;
+use Drupal\entity_test\Entity\EntityTest;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests the path validator.
+ *
+ * @group Path
+ *
+ * @see \Drupal\Core\Path\PathValidator
+ */
+class PathValidatorTest extends KernelTestBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ public static $modules = ['path', 'entity_test', 'user'];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp() {
+ parent::setUp();
+ $this->installEntitySchema('entity_test');
+ }
+
+ public function testGetUrlIfValidWithoutAccessCheck() {
+ $requestContext = \Drupal::service('router.request_context');
+ $pathValidator = \Drupal::service('path.validator');
+
+ $entity = EntityTest::create([
+ 'name' => 'test',
+ ]);
+ $entity->save();
+
+ $methods = [
+ 'POST',
+ 'GET',
+ 'PUT',
+ 'PATCH',
+ 'DELETE',
+ NULL, // Used in CLI context.
+ FALSE, // If no request was even pushed onto the request stack, and hence
+ ];
+ foreach ($methods as $method) {
+ if ($method === FALSE) {
+ $request_stack = $this->container->get('request_stack');
+ while ($request_stack->getCurrentRequest()) {
+ $request_stack->pop();
+ }
+ $this->container->set('router.request_context', new RequestContext());
+ }
+
+ $requestContext->setMethod($method);
+ /** @var \Drupal\Core\Url $url */
+ $url = $pathValidator->getUrlIfValidWithoutAccessCheck($entity->toUrl()->toString(TRUE)->getGeneratedUrl());
+ $this->assertEquals($method, $requestContext->getMethod());
+ $this->assertInstanceOf(Url::class, $url);
+ $this->assertSame($url->getRouteParameters(), ['entity_test' => $entity->id()]);
+ }
+ }
+
+}