diff --git a/libraries/classes/DatabaseInterface.php b/libraries/classes/DatabaseInterface.php index 25bf4dac7e..ec8f9a3288 100644 --- a/libraries/classes/DatabaseInterface.php +++ b/libraries/classes/DatabaseInterface.php @@ -3156,4 +3156,17 @@ class DatabaseInterface $dbi = new self(new DbiMysqli()); return $dbi; } + + /** + * Prepare an SQL statement for execution. + * + * @param string $query The query, as a string. + * @param int $link Link type. + * + * @return object|false A statement object or false. + */ + public function prepare(string $query, $link = DatabaseInterface::CONNECT_USER) + { + return $this->_extension->prepare($this->_links[$link], $query); + } } diff --git a/libraries/classes/Dbi/DbiExtension.php b/libraries/classes/Dbi/DbiExtension.php index 8cfa9fcd31..3d814cd62b 100644 --- a/libraries/classes/Dbi/DbiExtension.php +++ b/libraries/classes/Dbi/DbiExtension.php @@ -245,4 +245,14 @@ interface DbiExtension * @return string a MySQL escaped string */ public function escapeString($link, $str); + + /** + * Prepare an SQL statement for execution. + * + * @param mixed $link database link + * @param string $query The query, as a string. + * + * @return object|false A statement object or false. + */ + public function prepare($link, string $query); } diff --git a/libraries/classes/Dbi/DbiMysqli.php b/libraries/classes/Dbi/DbiMysqli.php index 4ebda25460..de07db1896 100644 --- a/libraries/classes/Dbi/DbiMysqli.php +++ b/libraries/classes/Dbi/DbiMysqli.php @@ -11,6 +11,7 @@ namespace PhpMyAdmin\Dbi; use mysqli; use mysqli_result; +use mysqli_stmt; use PhpMyAdmin\DatabaseInterface; use stdClass; use function mysqli_init; @@ -606,4 +607,17 @@ class DbiMysqli implements DbiExtension { return $mysqli->real_escape_string($string); } + + /** + * Prepare an SQL statement for execution. + * + * @param mysqli $mysqli database link + * @param string $query The query, as a string. + * + * @return mysqli_stmt|false A statement object or false. + */ + public function prepare($mysqli, string $query) + { + return $mysqli->prepare($query); + } } diff --git a/libraries/classes/Server/Privileges.php b/libraries/classes/Server/Privileges.php index 0a824bfd65..1545fdab18 100644 --- a/libraries/classes/Server/Privileges.php +++ b/libraries/classes/Server/Privileges.php @@ -1516,12 +1516,21 @@ class Privileges SELECT `User`, `Host`, `Db`, \'t\' AS `Type`, `Table_name`, `Table_priv` FROM `mysql`.`tables_priv` WHERE - \'' . $this->dbi->escapeString($db) . '\' LIKE `Db` AND - \'' . $this->dbi->escapeString($table) . '\' LIKE `Table_name` AND + ? LIKE `Db` AND + ? LIKE `Table_name` AND NOT (`Table_priv` = \'\' AND Column_priv = \'\') ORDER BY `User` ASC, `Host` ASC, `Db` ASC, `Table_priv` ASC; '; - $result = $this->dbi->query($query); + $statement = $this->dbi->prepare($query); + if ($statement === false + || ! $statement->bind_param('ss', $db, $table) + || ! $statement->execute() + ) { + return []; + } + + $result = $statement->get_result(); + $statement->close(); if ($result === false) { return []; } diff --git a/test/classes/Stubs/DbiDummy.php b/test/classes/Stubs/DbiDummy.php index e25bf0c311..59f5bddbe8 100644 --- a/test/classes/Stubs/DbiDummy.php +++ b/test/classes/Stubs/DbiDummy.php @@ -452,6 +452,16 @@ class DbiDummy implements DbiExtension ]; } + /** + * @param mixed $link link + * @param string $query query + * @return object|false + */ + public function prepare($link, string $query) + { + return false; + } + /** * Return query data for ID *