Ignore invalid routes cache file

If the `libraries/cache/routes.cache.php` file is invalid (usually from
5.1), ignores it and try to write a new one instead of failing.

Fixes https://github.com/phpmyadmin/phpmyadmin/issues/17522.

Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
This commit is contained in:
Maurício Meneghini Fauth 2022-05-13 16:45:21 -03:00
parent 4590194c71
commit 680e59eb5f
No known key found for this signature in database
GPG Key ID: 6A16FD38AFC89CC8
4 changed files with 123 additions and 6 deletions

View File

@ -9,9 +9,9 @@ use FastRoute\Dispatcher;
use FastRoute\Dispatcher\GroupCountBased as DispatcherGroupCountBased;
use FastRoute\RouteCollector;
use FastRoute\RouteParser\Std as RouteParserStd;
use PhpMyAdmin\Controllers\HomeController;
use PhpMyAdmin\Http\ServerRequest;
use Psr\Container\ContainerInterface;
use RuntimeException;
use function __;
use function file_exists;
@ -28,6 +28,7 @@ use function var_export;
use const CACHE_DIR;
use const E_USER_WARNING;
use const ROOT_PATH;
/**
* Class used to warm up the routing cache and manage routing.
@ -73,13 +74,11 @@ class Routing
// If skip cache is enabled, do not try to read the file
// If no cache skipping then read it and use it
if (! $skipCache && file_exists(self::ROUTES_CACHE_FILE)) {
/** @psalm-suppress MissingFile, UnresolvableInclude */
/** @psalm-suppress MissingFile, UnresolvableInclude, MixedAssignment */
$dispatchData = require self::ROUTES_CACHE_FILE;
if (! is_array($dispatchData)) {
throw new RuntimeException('Invalid cache file "' . self::ROUTES_CACHE_FILE . '"');
if (self::isRoutesCacheFileValid($dispatchData)) {
return new DispatcherGroupCountBased($dispatchData);
}
return new DispatcherGroupCountBased($dispatchData);
}
$routeCollector = new RouteCollector(
@ -191,4 +190,19 @@ class Routing
$controller = $container->get($controllerName);
$controller($request, $vars);
}
/**
* @param mixed $dispatchData
*
* @psalm-assert-if-true array[] $dispatchData
*/
private static function isRoutesCacheFileValid($dispatchData): bool
{
return is_array($dispatchData)
&& isset($dispatchData[0], $dispatchData[1])
&& is_array($dispatchData[0]) && is_array($dispatchData[1])
&& isset($dispatchData[0]['GET']) && is_array($dispatchData[0]['GET'])
&& isset($dispatchData[0]['GET']['/']) && is_string($dispatchData[0]['GET']['/'])
&& $dispatchData[0]['GET']['/'] === HomeController::class;
}
}

View File

@ -8,6 +8,11 @@ use FastRoute\Dispatcher;
use PhpMyAdmin\Controllers\HomeController;
use PhpMyAdmin\Routing;
use function copy;
use const CACHE_DIR;
use const ROOT_PATH;
/**
* @covers \PhpMyAdmin\Routing
*/
@ -26,6 +31,52 @@ class RoutingTest extends AbstractTestCase
);
}
public function testGetDispatcherWithValidCacheFile(): void
{
$GLOBALS['cfg']['environment'] = null;
$this->assertDirectoryIsWritable(CACHE_DIR);
$this->assertTrue(copy(
ROOT_PATH . 'test/test_data/routes/routes-valid.cache.txt',
CACHE_DIR . 'routes.cache.php'
));
$dispatcher = Routing::getDispatcher();
$this->assertInstanceOf(Dispatcher::class, $dispatcher);
$this->assertSame(
[Dispatcher::FOUND, HomeController::class, []],
$dispatcher->dispatch('GET', '/')
);
$this->assertFileEquals(
CACHE_DIR . 'routes.cache.php',
ROOT_PATH . 'test/test_data/routes/routes-valid.cache.txt'
);
}
public function testGetDispatcherWithInvalidCacheFile(): void
{
$GLOBALS['cfg']['environment'] = null;
$this->assertDirectoryIsWritable(CACHE_DIR);
$this->assertTrue(copy(
ROOT_PATH . 'test/test_data/routes/routes-invalid.cache.txt',
CACHE_DIR . 'routes.cache.php'
));
$dispatcher = Routing::getDispatcher();
$this->assertInstanceOf(Dispatcher::class, $dispatcher);
$this->assertSame(
[Dispatcher::FOUND, HomeController::class, []],
$dispatcher->dispatch('GET', '/')
);
$this->assertFileNotEquals(
CACHE_DIR . 'routes.cache.php',
ROOT_PATH . 'test/test_data/routes/routes-invalid.cache.txt'
);
}
/**
* Test for Routing::getCurrentRoute
*/

View File

@ -0,0 +1,34 @@
<?php return array (
0 =>
array (
'GET' =>
array (
'' =>
array (
0 => 'PhpMyAdmin\\Controllers\\HomeController',
1 => 'index',
),
'/' =>
array (
0 => 'PhpMyAdmin\\Controllers\\HomeController',
1 => 'index',
),
),
'POST' =>
array (
'' =>
array (
0 => 'PhpMyAdmin\\Controllers\\HomeController',
1 => 'index',
),
'/' =>
array (
0 => 'PhpMyAdmin\\Controllers\\HomeController',
1 => 'index',
),
),
),
1 =>
array (
),
);

View File

@ -0,0 +1,18 @@
<?php return array (
0 =>
array (
'GET' =>
array (
'' => 'PhpMyAdmin\\Controllers\\HomeController',
'/' => 'PhpMyAdmin\\Controllers\\HomeController',
),
'POST' =>
array (
'' => 'PhpMyAdmin\\Controllers\\HomeController',
'/' => 'PhpMyAdmin\\Controllers\\HomeController',
),
),
1 =>
array (
),
);