From 22c6a2f9d87947eb4e686690cb5a1397322d40b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Tue, 6 Jun 2023 21:04:05 -0300 Subject: [PATCH] Add a wrapper around the exit language construct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Creates the PhpMyAdmin\ResponseRenderer::callExit() method as a wrapper to the exit language construct. That makes the tests more correct as the method will always stop the code execution. Signed-off-by: MaurĂ­cio Meneghini Fauth --- libraries/classes/Config/PageSettings.php | 2 +- .../Controllers/AbstractController.php | 4 +- .../Controllers/Export/ExportController.php | 2 +- .../Controllers/Table/RelationController.php | 2 +- .../Table/Structure/SaveController.php | 2 +- libraries/classes/Database/Events.php | 10 ++-- libraries/classes/Database/Routines.php | 22 ++++----- libraries/classes/DatabaseInterface.php | 2 +- libraries/classes/DbTableExists.php | 8 ++-- libraries/classes/ErrorHandler.php | 9 +--- .../classes/Exceptions/ExitException.php | 14 ++++++ libraries/classes/Html/Generator.php | 4 +- libraries/classes/Import.php | 4 +- libraries/classes/Pdf.php | 2 +- .../Plugins/Auth/AuthenticationConfig.php | 11 +---- .../Plugins/Auth/AuthenticationCookie.php | 34 ++++--------- .../Plugins/Auth/AuthenticationHttp.php | 17 ++----- .../Plugins/Auth/AuthenticationSignon.php | 17 ++----- .../classes/Plugins/AuthenticationPlugin.php | 12 ++--- .../Plugins/Schema/ExportRelationSchema.php | 3 +- .../classes/Plugins/Schema/TableStats.php | 3 +- libraries/classes/ResponseRenderer.php | 21 ++++++-- libraries/classes/Sql.php | 6 +-- libraries/classes/Triggers/Triggers.php | 10 ++-- libraries/classes/UrlRedirector.php | 4 +- psalm-baseline.xml | 10 ++++ .../Controllers/AbstractControllerTest.php | 9 +++- test/classes/ErrorHandlerTest.php | 30 ++++++++++-- .../Plugins/Auth/AuthenticationConfigTest.php | 17 +++++-- .../Plugins/Auth/AuthenticationCookieTest.php | 48 +++++++++++++++---- .../Plugins/Auth/AuthenticationHttpTest.php | 15 ++++-- .../Plugins/Auth/AuthenticationSignonTest.php | 10 +++- test/classes/Setup/FormProcessingTest.php | 2 + test/classes/Stubs/ResponseRenderer.php | 6 +++ 34 files changed, 222 insertions(+), 150 deletions(-) create mode 100644 libraries/classes/Exceptions/ExitException.php diff --git a/libraries/classes/Config/PageSettings.php b/libraries/classes/Config/PageSettings.php index 872e8c8017..cf8a7dd150 100644 --- a/libraries/classes/Config/PageSettings.php +++ b/libraries/classes/Config/PageSettings.php @@ -98,7 +98,7 @@ class PageSettings // reload page $response = ResponseRenderer::getInstance(); Core::sendHeaderLocation($response->getSelfUrl()); - exit; + $response->callExit(); } return $result; diff --git a/libraries/classes/Controllers/AbstractController.php b/libraries/classes/Controllers/AbstractController.php index 83f8dd5c6b..ec1e37233d 100644 --- a/libraries/classes/Controllers/AbstractController.php +++ b/libraries/classes/Controllers/AbstractController.php @@ -133,9 +133,7 @@ abstract class AbstractController $this->response->setRequestStatus(false); $this->response->addHTML(Message::error($errorMessage)->getDisplay()); - if (! defined('TESTSUITE')) { - exit; - } + $this->response->callExit(); } /** @psalm-param int<400,599> $statusCode */ diff --git a/libraries/classes/Controllers/Export/ExportController.php b/libraries/classes/Controllers/Export/ExportController.php index 2647111a80..cff1fafb19 100644 --- a/libraries/classes/Controllers/Export/ExportController.php +++ b/libraries/classes/Controllers/Export/ExportController.php @@ -311,7 +311,7 @@ final class ExportController extends AbstractController /** @var DatabaseExportController $controller */ $controller = Core::getContainerBuilder()->get(DatabaseExportController::class); $controller($request); - exit; + $this->response->callExit(); } } diff --git a/libraries/classes/Controllers/Table/RelationController.php b/libraries/classes/Controllers/Table/RelationController.php index 872ab61d1f..151c93c8fa 100644 --- a/libraries/classes/Controllers/Table/RelationController.php +++ b/libraries/classes/Controllers/Table/RelationController.php @@ -269,7 +269,7 @@ final class RelationController extends AbstractController if (isset($_POST['preview_sql'])) { Core::previewSQL($previewSqlData); - exit; + $this->response->callExit(); } if (empty($displayQuery) || $seenError) { diff --git a/libraries/classes/Controllers/Table/Structure/SaveController.php b/libraries/classes/Controllers/Table/Structure/SaveController.php index c5651e0f2b..eaa4d5d624 100644 --- a/libraries/classes/Controllers/Table/Structure/SaveController.php +++ b/libraries/classes/Controllers/Table/Structure/SaveController.php @@ -147,7 +147,7 @@ final class SaveController extends AbstractController if (isset($_POST['preview_sql'])) { Core::previewSQL($changes !== [] ? $sqlQuery : ''); - exit; + $this->response->callExit(); } $columnsWithIndex = $this->dbi diff --git a/libraries/classes/Database/Events.php b/libraries/classes/Database/Events.php index 81f2792ba2..3be72ed573 100644 --- a/libraries/classes/Database/Events.php +++ b/libraries/classes/Database/Events.php @@ -200,7 +200,7 @@ class Events } $this->response->addJSON('tableType', 'events'); - exit; + $this->response->callExit(); } } @@ -508,7 +508,7 @@ class Events unset($_POST); } - exit; + $this->response->callExit(); } $message = __('Error in processing request:') . ' '; @@ -521,7 +521,7 @@ class Events if ($this->response->isAjax()) { $this->response->setRequestStatus(false); $this->response->addJSON('message', $message); - exit; + $this->response->callExit(); } echo $message->getDisplay(); @@ -549,7 +549,7 @@ class Events $this->response->addJSON('message', $exportData); $this->response->addJSON('title', $title); - exit; + $this->response->callExit(); } $output = '
'; @@ -574,7 +574,7 @@ class Events $this->response->setRequestStatus(false); $this->response->addJSON('message', $message); - exit; + $this->response->callExit(); } $this->response->addHTML($message->getDisplay()); diff --git a/libraries/classes/Database/Routines.php b/libraries/classes/Database/Routines.php index a91d403bc0..4760fe0058 100644 --- a/libraries/classes/Database/Routines.php +++ b/libraries/classes/Database/Routines.php @@ -134,7 +134,7 @@ class Routines echo "\n\n

" . $title . "

\n\n" . $editor; } - exit; + $this->response->callExit(); } $message = __('Error in processing request:') . ' '; @@ -153,7 +153,7 @@ class Routines if ($this->response->isAjax()) { $this->response->setRequestStatus(false); $this->response->addJSON('message', $message); - exit; + $this->response->callExit(); } echo $message->getDisplay(); @@ -268,7 +268,7 @@ class Routines if (! $GLOBALS['message']->isSuccess()) { $this->response->setRequestStatus(false); $this->response->addJSON('message', $output); - exit; + $this->response->callExit(); } $routines = self::getDetails($this->dbi, $db, $_POST['item_type'], $_POST['item_name']); @@ -283,7 +283,7 @@ class Routines $this->response->addJSON('insert', ! empty($routine)); $this->response->addJSON('message', $output); $this->response->addJSON('tableType', 'routines'); - exit; + $this->response->callExit(); } /** @@ -1127,7 +1127,7 @@ class Routines if ($this->response->isAjax()) { $this->response->setRequestStatus(false); $this->response->addJSON('message', $message); - exit; + $this->response->callExit(); } echo $message->getDisplay(); @@ -1237,14 +1237,14 @@ class Routines $this->response->setRequestStatus($message->isSuccess()); $this->response->addJSON('message', $message->getDisplay() . $output); $this->response->addJSON('dialog', false); - exit; + $this->response->callExit(); } echo $message->getDisplay() , $output; if ($message->isError()) { // At least one query has failed, so shouldn't // execute any more queries, so we quit. - exit; + $this->response->callExit(); } unset($_POST); @@ -1280,7 +1280,7 @@ class Routines echo $form; } - exit; + $this->response->callExit(); } if ($this->response->isAjax()) { @@ -1294,7 +1294,7 @@ class Routines $this->response->setRequestStatus(false); $this->response->addJSON('message', $message); - exit; + $this->response->callExit(); } } } @@ -1545,7 +1545,7 @@ class Routines $this->response->addJSON('message', $exportData); $this->response->addJSON('title', $title); - exit; + $this->response->callExit(); } $output = '
'; @@ -1573,7 +1573,7 @@ class Routines $this->response->setRequestStatus(false); $this->response->addJSON('message', $message); - exit; + $this->response->callExit(); } $this->response->addHTML($message->getDisplay()); diff --git a/libraries/classes/DatabaseInterface.php b/libraries/classes/DatabaseInterface.php index 80dc82a039..f77587ccf6 100644 --- a/libraries/classes/DatabaseInterface.php +++ b/libraries/classes/DatabaseInterface.php @@ -165,7 +165,7 @@ class DatabaseInterface implements DbalInterface // The following statement will exit Generator::mysqlDie($this->getError($connectionType), $query); - exit; + ResponseRenderer::getInstance()->callExit(); } return $result; diff --git a/libraries/classes/DbTableExists.php b/libraries/classes/DbTableExists.php index 3a62acaa32..b141e930a2 100644 --- a/libraries/classes/DbTableExists.php +++ b/libraries/classes/DbTableExists.php @@ -46,7 +46,7 @@ final class DbTableExists Message::error(__('No databases selected.')), ); - exit; + $response->callExit(); } $urlParams = ['reload' => 1]; @@ -65,7 +65,7 @@ final class DbTableExists Core::sendHeaderLocation('./index.php?route=/' . Url::getCommonRaw($urlParams, '&')); - exit; + $response->callExit(); } private static function checkTable(string $db, string $table, bool $isTransformationWrapper): void @@ -90,7 +90,7 @@ final class DbTableExists } if ($isTransformationWrapper) { - exit; + ResponseRenderer::getInstance()->callExit(); } if ($table !== '') { @@ -110,6 +110,6 @@ final class DbTableExists $controller = Core::getContainerBuilder()->get(SqlController::class); $controller(Common::getRequest()); - exit; + ResponseRenderer::getInstance()->callExit(); } } diff --git a/libraries/classes/ErrorHandler.php b/libraries/classes/ErrorHandler.php index 4fd667c74f..7d628fd2d8 100644 --- a/libraries/classes/ErrorHandler.php +++ b/libraries/classes/ErrorHandler.php @@ -300,9 +300,6 @@ class ErrorHandler default: // FATAL error, display it and exit $this->dispFatalError($error); - if (! defined('TESTSUITE')) { - exit; - } } } @@ -325,7 +322,7 @@ class ErrorHandler * * @param Error $error the error */ - protected function dispFatalError(Error $error): void + protected function dispFatalError(Error $error): never { $response = ResponseRenderer::getInstance(); if (! $response->headersSent()) { @@ -337,9 +334,7 @@ class ErrorHandler $response->addHTML($error->getDisplay()); $response->addHTML(''); - if (! defined('TESTSUITE')) { - exit; - } + $response->callExit(); } /** diff --git a/libraries/classes/Exceptions/ExitException.php b/libraries/classes/Exceptions/ExitException.php new file mode 100644 index 0000000000..754f9717fd --- /dev/null +++ b/libraries/classes/Exceptions/ExitException.php @@ -0,0 +1,14 @@ +isAjax()) { $response->setRequestStatus(false); $response->addJSON('message', $errorMessage); - exit; + $response->callExit(); } if ($backUrl !== '') { @@ -906,7 +906,7 @@ class Generator . '' . "\n\n"; } - exit($errorMessage); + $response->callExit($errorMessage); } /** diff --git a/libraries/classes/Import.php b/libraries/classes/Import.php index 278435bd6e..08cc153641 100644 --- a/libraries/classes/Import.php +++ b/libraries/classes/Import.php @@ -1024,7 +1024,7 @@ class Import /* TODO: Do more checking here to make sure they really are matched */ if (count($tables) != count($analyses)) { - exit; + ResponseRenderer::getInstance()->callExit(); } /* Create SQL code to create the tables */ @@ -1321,7 +1321,7 @@ class Import $response = ResponseRenderer::getInstance(); $message = Message::rawError($error); $response->addJSON('message', $message); - exit; + $response->callExit(); } // If everything fine, START a transaction. diff --git a/libraries/classes/Pdf.php b/libraries/classes/Pdf.php index 1fb9c5de71..6842999a5b 100644 --- a/libraries/classes/Pdf.php +++ b/libraries/classes/Pdf.php @@ -135,6 +135,6 @@ class Pdf extends TCPDF echo Message::error( __('Error while creating PDF:') . ' ' . $errorMessage, )->getDisplay(); - exit; + ResponseRenderer::getInstance()->callExit(); } } diff --git a/libraries/classes/Plugins/Auth/AuthenticationConfig.php b/libraries/classes/Plugins/Auth/AuthenticationConfig.php index 8f326bf118..3855062a0f 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationConfig.php +++ b/libraries/classes/Plugins/Auth/AuthenticationConfig.php @@ -15,7 +15,6 @@ use PhpMyAdmin\Util; use function __; use function count; -use function defined; use function sprintf; use function trigger_error; @@ -39,11 +38,7 @@ class AuthenticationConfig extends AuthenticationPlugin $response->setRequestStatus(false); // reload_flag removes the token parameter from the URL and reloads $response->addJSON('reload_flag', '1'); - if (defined('TESTSUITE')) { - return true; - } - - exit; + $response->callExit(); } return true; @@ -160,8 +155,6 @@ class AuthenticationConfig extends AuthenticationPlugin } echo '' , "\n"; - if (! defined('TESTSUITE')) { - exit; - } + $response->callExit(); } } diff --git a/libraries/classes/Plugins/Auth/AuthenticationCookie.php b/libraries/classes/Plugins/Auth/AuthenticationCookie.php index d1229b457d..23366e32a5 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationCookie.php +++ b/libraries/classes/Plugins/Auth/AuthenticationCookie.php @@ -29,7 +29,6 @@ use function array_keys; use function base64_decode; use function base64_encode; use function count; -use function defined; use function explode; use function function_exists; use function in_array; @@ -77,11 +76,7 @@ class AuthenticationCookie extends AuthenticationPlugin */ $sessionExpired = isset($_REQUEST['check_timeout']) || isset($_REQUEST['session_timedout']); if (! $sessionExpired && $response->loginPage()) { - if (defined('TESTSUITE')) { - return true; - } - - exit; + $response->callExit(); } /** @@ -202,11 +197,7 @@ class AuthenticationCookie extends AuthenticationPlugin 'config_footer' => $configFooter, ]); - if (! defined('TESTSUITE')) { - exit; - } - - return true; + $response->callExit(); } /** @@ -336,7 +327,7 @@ class AuthenticationCookie extends AuthenticationPlugin 'error_message' => $exception->getMessage(), ]); - exit; + ResponseRenderer::getInstance()->callExit(); } return true; @@ -388,11 +379,7 @@ class AuthenticationCookie extends AuthenticationPlugin SessionCache::remove('proc_priv'); $this->showFailure('no-activity'); - if (! defined('TESTSUITE')) { - exit; - } - - return false; + ResponseRenderer::getInstance()->callExit(); } // check password cookie @@ -492,11 +479,7 @@ class AuthenticationCookie extends AuthenticationPlugin $response->addJSON('success', 1); $response->addJSON('new_token', $_SESSION[' PMA_token ']); - if (! defined('TESTSUITE')) { - exit; - } - - return; + $response->callExit(); } // Set server cookies if required (once per session) and, in this case, @@ -510,16 +493,15 @@ class AuthenticationCookie extends AuthenticationPlugin */ Util::clearUserCache(); - ResponseRenderer::getInstance()->disable(); + $response = ResponseRenderer::getInstance(); + $response->disable(); Core::sendHeaderLocation( './index.php?route=/' . Url::getCommonRaw($urlParams, '&'), true, ); - if (! defined('TESTSUITE')) { - exit; - } + $response->callExit(); } /** diff --git a/libraries/classes/Plugins/Auth/AuthenticationHttp.php b/libraries/classes/Plugins/Auth/AuthenticationHttp.php index 9c3b7fa9f8..ca8358200c 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationHttp.php +++ b/libraries/classes/Plugins/Auth/AuthenticationHttp.php @@ -16,7 +16,6 @@ use PhpMyAdmin\ResponseRenderer; use function __; use function base64_decode; -use function defined; use function hash_equals; use function preg_replace; use function sprintf; @@ -41,11 +40,7 @@ class AuthenticationHttp extends AuthenticationPlugin $response->setRequestStatus(false); // reload_flag removes the token parameter from the URL and reloads $response->addJSON('reload_flag', '1'); - if (defined('TESTSUITE')) { - return true; - } - - exit; + $response->callExit(); } return $this->authForm(); @@ -95,11 +90,7 @@ class AuthenticationHttp extends AuthenticationPlugin $response->addHTML(Config::renderFooter()); - if (! defined('TESTSUITE')) { - exit; - } - - return false; + $response->callExit(); } /** @@ -200,9 +191,7 @@ class AuthenticationHttp extends AuthenticationPlugin 'error_message' => $error, ]); - if (! defined('TESTSUITE')) { - exit; - } + ResponseRenderer::getInstance()->callExit(); } $this->authForm(); diff --git a/libraries/classes/Plugins/Auth/AuthenticationSignon.php b/libraries/classes/Plugins/Auth/AuthenticationSignon.php index b74ea4b23e..418bb7f7a5 100644 --- a/libraries/classes/Plugins/Auth/AuthenticationSignon.php +++ b/libraries/classes/Plugins/Auth/AuthenticationSignon.php @@ -31,12 +31,11 @@ class AuthenticationSignon extends AuthenticationPlugin { /** * Displays authentication form - * - * @return bool always true (no return indeed) */ public function showLoginForm(): bool { - ResponseRenderer::getInstance()->disable(); + $response = ResponseRenderer::getInstance(); + $response->disable(); unset($_SESSION['LAST_SIGNON_URL']); if (empty($GLOBALS['cfg']['Server']['SignonURL'])) { echo $this->template->render('error/generic', [ @@ -45,18 +44,12 @@ class AuthenticationSignon extends AuthenticationPlugin 'error_message' => 'You must set SignonURL!', ]); - if (! defined('TESTSUITE')) { - exit; - } + $response->callExit(); } else { Core::sendHeaderLocation($GLOBALS['cfg']['Server']['SignonURL']); } - if (! defined('TESTSUITE')) { - exit; - } - - return false; + $response->callExit(); } /** @@ -136,7 +129,7 @@ class AuthenticationSignon extends AuthenticationPlugin 'error_message' => __('Can not find signon authentication script:') . ' ' . $scriptName, ]); - exit; + ResponseRenderer::getInstance()->callExit(); } include $scriptName; diff --git a/libraries/classes/Plugins/AuthenticationPlugin.php b/libraries/classes/Plugins/AuthenticationPlugin.php index dfecea57f8..a13f05611e 100644 --- a/libraries/classes/Plugins/AuthenticationPlugin.php +++ b/libraries/classes/Plugins/AuthenticationPlugin.php @@ -248,7 +248,7 @@ abstract class AuthenticationPlugin 'error_message' => $exception->getMessage(), ]); - exit; + ResponseRenderer::getInstance()->callExit(); } $this->showLoginForm(); @@ -313,11 +313,7 @@ abstract class AuthenticationPlugin $response = ResponseRenderer::getInstance(); if ($response->loginPage()) { - if (defined('TESTSUITE')) { - return; - } - - exit; + $response->callExit(); } echo $this->template->render('login/header'); @@ -330,8 +326,6 @@ abstract class AuthenticationPlugin ]); echo $this->template->render('login/footer'); echo Config::renderFooter(); - if (! defined('TESTSUITE')) { - exit; - } + $response->callExit(); } } diff --git a/libraries/classes/Plugins/Schema/ExportRelationSchema.php b/libraries/classes/Plugins/Schema/ExportRelationSchema.php index 333a8e4297..b3fbc6c4f5 100644 --- a/libraries/classes/Plugins/Schema/ExportRelationSchema.php +++ b/libraries/classes/Plugins/Schema/ExportRelationSchema.php @@ -10,6 +10,7 @@ namespace PhpMyAdmin\Plugins\Schema; use PhpMyAdmin\ConfigStorage\Relation; use PhpMyAdmin\Identifiers\DatabaseName; +use PhpMyAdmin\ResponseRenderer; use PhpMyAdmin\Url; use PhpMyAdmin\Util; @@ -268,6 +269,6 @@ class ExportRelationSchema ]); echo '">' . __('Back') . ''; echo "\n"; - exit; + ResponseRenderer::getInstance()->callExit(); } } diff --git a/libraries/classes/Plugins/Schema/TableStats.php b/libraries/classes/Plugins/Schema/TableStats.php index b261601529..ad10d1ec39 100644 --- a/libraries/classes/Plugins/Schema/TableStats.php +++ b/libraries/classes/Plugins/Schema/TableStats.php @@ -10,6 +10,7 @@ namespace PhpMyAdmin\Plugins\Schema; use PhpMyAdmin\ConfigStorage\Relation; use PhpMyAdmin\Font; use PhpMyAdmin\Index; +use PhpMyAdmin\ResponseRenderer; use PhpMyAdmin\Util; use function array_flip; @@ -91,7 +92,7 @@ abstract class TableStats $result = $GLOBALS['dbi']->tryQuery($sql); if (! $result || ! $result->numRows()) { $this->showMissingTableError(); - exit; + ResponseRenderer::getInstance()->callExit(); } if ($this->showKeys) { diff --git a/libraries/classes/ResponseRenderer.php b/libraries/classes/ResponseRenderer.php index 0d5815d3c6..cf05ce51d0 100644 --- a/libraries/classes/ResponseRenderer.php +++ b/libraries/classes/ResponseRenderer.php @@ -7,6 +7,8 @@ declare(strict_types=1); namespace PhpMyAdmin; +use PhpMyAdmin\Exceptions\ExitException; + use function defined; use function header; use function headers_sent; @@ -378,7 +380,7 @@ class ResponseRenderer } $this->buffer->flush(); - exit; + $this->callExit(); } /** @@ -441,9 +443,7 @@ class ResponseRenderer { $this->setHttpResponseCode(303); $this->header('Location: ' . $location); - if (! defined('TESTSUITE')) { - exit; - } + $this->callExit(); } /** @@ -486,4 +486,17 @@ class ResponseRenderer { return $this->footer->getScripts(); } + + public function callExit(string $message = ''): never + { + if (defined('TESTSUITE')) { + throw new ExitException($message); + } + + if ($message !== '') { + exit($message); + } + + exit; + } } diff --git a/libraries/classes/Sql.php b/libraries/classes/Sql.php index c0f66ce309..c00618f361 100644 --- a/libraries/classes/Sql.php +++ b/libraries/classes/Sql.php @@ -489,16 +489,16 @@ class Sql */ private function handleQueryExecuteError(bool $isGotoFile, string $error, string $fullSqlQuery): never { + $response = ResponseRenderer::getInstance(); if ($isGotoFile) { $message = Message::rawError($error); - $response = ResponseRenderer::getInstance(); $response->setRequestStatus(false); $response->addJSON('message', $message); } else { Generator::mysqlDie($error, $fullSqlQuery, false); } - exit; + $response->callExit(); } /** @@ -1329,7 +1329,7 @@ class Sql // value of a transformed field, show it here if (isset($_POST['grid_edit']) && $_POST['grid_edit'] == true && is_object($result)) { $this->getResponseForGridEdit($result); - exit; + ResponseRenderer::getInstance()->callExit(); } // Gets the list of fields properties diff --git a/libraries/classes/Triggers/Triggers.php b/libraries/classes/Triggers/Triggers.php index 799a819786..7375c68ed2 100644 --- a/libraries/classes/Triggers/Triggers.php +++ b/libraries/classes/Triggers/Triggers.php @@ -189,7 +189,7 @@ class Triggers } $this->response->addJSON('tableType', 'triggers'); - exit; + $this->response->callExit(); } } @@ -412,7 +412,7 @@ class Triggers unset($_POST); } - exit; + $this->response->callExit(); } $message = __('Error in processing request:') . ' '; @@ -425,7 +425,7 @@ class Triggers if ($this->response->isAjax()) { $this->response->setRequestStatus(false); $this->response->addJSON('message', $message); - exit; + $this->response->callExit(); } echo $message->getDisplay(); @@ -451,7 +451,7 @@ class Triggers $this->response->addJSON('message', htmlspecialchars(trim($exportData))); $this->response->addJSON('title', $title); - exit; + $this->response->callExit(); } $this->response->addHTML($this->template->render('triggers/export', [ @@ -473,7 +473,7 @@ class Triggers $this->response->setRequestStatus(false); $this->response->addJSON('message', $message); - exit; + $this->response->callExit(); } $this->response->addHTML($message->getDisplay()); diff --git a/libraries/classes/UrlRedirector.php b/libraries/classes/UrlRedirector.php index 21c87bc5c6..ff17d10524 100644 --- a/libraries/classes/UrlRedirector.php +++ b/libraries/classes/UrlRedirector.php @@ -31,7 +31,7 @@ final class UrlRedirector ) { Core::sendHeaderLocation('./'); - exit; + $response->callExit(); } /** @@ -46,6 +46,6 @@ final class UrlRedirector // Do not display the value of $_GET['url'] to avoid showing injected content echo __('Taking you to the target site.'); - exit; + $response->callExit(); } } diff --git a/psalm-baseline.xml b/psalm-baseline.xml index e2165f70c3..228c91c193 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -8184,6 +8184,9 @@ + + bool + @@ -8247,6 +8250,7 @@ bool + bool @@ -8274,6 +8278,9 @@ $oldUser + + bool + @@ -8326,6 +8333,9 @@ issetCookie + + bool + diff --git a/test/classes/Controllers/AbstractControllerTest.php b/test/classes/Controllers/AbstractControllerTest.php index 233210f284..7b7bc52660 100644 --- a/test/classes/Controllers/AbstractControllerTest.php +++ b/test/classes/Controllers/AbstractControllerTest.php @@ -5,11 +5,13 @@ declare(strict_types=1); namespace PhpMyAdmin\Tests\Controllers; use PhpMyAdmin\Controllers\AbstractController; +use PhpMyAdmin\Exceptions\ExitException; use PhpMyAdmin\Html\MySQLDocumentation; use PhpMyAdmin\Message; use PhpMyAdmin\Template; use PhpMyAdmin\Tests\AbstractTestCase; use PhpMyAdmin\Tests\Stubs\ResponseRenderer; +use Throwable; /** @covers \PhpMyAdmin\Controllers\AbstractController */ class AbstractControllerTest extends AbstractTestCase @@ -45,7 +47,12 @@ class AbstractControllerTest extends AbstractTestCase $message .= '[br]'; $expected = Message::error($message)->getDisplay(); - $controller->testCheckParameters(['param1', 'param2']); + try { + $controller->testCheckParameters(['param1', 'param2']); + } catch (Throwable $throwable) { + } + + $this->assertInstanceOf(ExitException::class, $throwable ?? null); $this->assertSame($expected, $response->getHTMLResult()); $this->assertSame(400, $response->getHttpResponseCode()); } diff --git a/test/classes/ErrorHandlerTest.php b/test/classes/ErrorHandlerTest.php index f799f424d2..5e685713d1 100644 --- a/test/classes/ErrorHandlerTest.php +++ b/test/classes/ErrorHandlerTest.php @@ -7,9 +7,11 @@ namespace PhpMyAdmin\Tests; use Exception; use PhpMyAdmin\Error; use PhpMyAdmin\ErrorHandler; +use PhpMyAdmin\Exceptions\ExitException; use PhpMyAdmin\ResponseRenderer; use PhpMyAdmin\Tests\Stubs\ResponseRenderer as ResponseRendererStub; use ReflectionProperty; +use Throwable; use function array_keys; use function array_pop; @@ -304,7 +306,12 @@ class ErrorHandlerTest extends AbstractTestCase $responseStub->setHeadersSent(true); $errorHandler = new ErrorHandler(); $this->assertSame([], $errorHandler->getCurrentErrors()); - $errorHandler->handleException(new Exception('Exception message.')); + try { + $errorHandler->handleException(new Exception('Exception message.')); + } catch (Throwable $throwable) { + } + + $this->assertInstanceOf(ExitException::class, $throwable ?? null); $output = $responseStub->getHTMLResult(); $errors = $errorHandler->getCurrentErrors(); $this->assertCount(1, $errors); @@ -327,7 +334,12 @@ class ErrorHandlerTest extends AbstractTestCase $responseStub->setHeadersSent(true); $errorHandler = new ErrorHandler(); $this->assertSame([], $errorHandler->getCurrentErrors()); - $errorHandler->handleException(new Exception('Exception message.')); + try { + $errorHandler->handleException(new Exception('Exception message.')); + } catch (Throwable $throwable) { + } + + $this->assertInstanceOf(ExitException::class, $throwable ?? null); $output = $responseStub->getHTMLResult(); $errors = $errorHandler->getCurrentErrors(); $this->assertCount(1, $errors); @@ -348,7 +360,12 @@ class ErrorHandlerTest extends AbstractTestCase (new ReflectionProperty(ResponseRenderer::class, 'instance'))->setValue($responseStub); $responseStub->setHeadersSent(true); $errorHandler = new ErrorHandler(); - $errorHandler->addError('Fatal error message!', E_ERROR, './file/name', 1); + try { + $errorHandler->addError('Fatal error message!', E_ERROR, './file/name', 1); + } catch (Throwable $exception) { + } + + $this->assertInstanceOf(ExitException::class, $exception ?? null); // phpcs:disable Generic.Files.LineLength.TooLong $expectedStart = <<<'HTML'