Skip to content

Commit e6f8623

Browse files
Merge pull request #17921 from kamil-tekiela/like
Clean up LIKE escaping
2 parents 95c9fa4 + dd699f3 commit e6f8623

15 files changed

Lines changed: 208 additions & 209 deletions

File tree

libraries/classes/Controllers/Server/PrivilegesController.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
use PhpMyAdmin\Server\Privileges;
1919
use PhpMyAdmin\Template;
2020
use PhpMyAdmin\Url;
21-
use PhpMyAdmin\Util;
2221

2322
use function __;
2423
use function header;
@@ -387,7 +386,7 @@ public function __invoke(ServerRequest $request): void
387386
if (isset($_GET['adduser']) || $GLOBALS['_add_user_error'] === true) {
388387
// Add user
389388
$this->response->addHTML($serverPrivileges->getHtmlForAddUser(
390-
Util::escapeMysqlWildcards(is_string($GLOBALS['dbname']) ? $GLOBALS['dbname'] : '')
389+
$serverPrivileges->escapeGrantWildcards(is_string($GLOBALS['dbname']) ? $GLOBALS['dbname'] : '')
391390
));
392391
} else {
393392
if (isset($GLOBALS['dbname']) && ! is_array($GLOBALS['dbname'])) {
@@ -418,7 +417,7 @@ public function __invoke(ServerRequest $request): void
418417
$GLOBALS['hostname'] ?? '',
419418
is_string($GLOBALS['dbname']) ? $GLOBALS['dbname'] : '',
420419
$GLOBALS['routinename'],
421-
Util::escapeMysqlWildcards($GLOBALS['url_dbname'] ?? '')
420+
$serverPrivileges->escapeGrantWildcards($GLOBALS['url_dbname'] ?? '')
422421
)
423422
);
424423
} else {
@@ -431,7 +430,7 @@ public function __invoke(ServerRequest $request): void
431430
$this->response->addHTML(
432431
$serverPrivileges->getHtmlForUserProperties(
433432
$GLOBALS['dbname_is_wildcard'],
434-
Util::escapeMysqlWildcards($GLOBALS['url_dbname'] ?? ''),
433+
$serverPrivileges->escapeGrantWildcards($GLOBALS['url_dbname'] ?? ''),
435434
$GLOBALS['username'],
436435
$GLOBALS['hostname'] ?? '',
437436
$GLOBALS['dbname'] ?? '',

libraries/classes/DatabaseInterface.php

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,21 @@ public function getTablesFull(
391391
$tables = [];
392392

393393
if (! $GLOBALS['cfg']['Server']['DisableIS']) {
394-
$sqlWhereTable = QueryGenerator::getTableCondition(
395-
is_array($table) ? array_map([$this, 'escapeString'], $table) : $this->escapeString($table),
396-
$tableIsGroup,
397-
$tableType
398-
);
394+
$sqlWhereTable = '';
395+
if ($table !== [] && $table !== '') {
396+
if (is_array($table)) {
397+
$sqlWhereTable = QueryGenerator::getTableNameConditionForMultiple(
398+
array_map([$this, 'quoteString'], $table)
399+
);
400+
} else {
401+
$sqlWhereTable = QueryGenerator::getTableNameCondition(
402+
$this->quoteString($tableIsGroup ? $this->escapeMysqlWildcards($table) : $table),
403+
$tableIsGroup
404+
);
405+
}
406+
}
407+
408+
$sqlWhereTable .= QueryGenerator::getTableTypeCondition($tableType);
399409

400410
// for PMA bc:
401411
// `SCHEMA_FIELD_NAME` AS `SHOW_TABLE_STATUS_FIELD_NAME`
@@ -405,7 +415,7 @@ public function getTablesFull(
405415
// comparison (if we are looking for the db Aa we don't want
406416
// to find the db aa)
407417

408-
$sql = QueryGenerator::getSqlForTablesFull([$this->escapeString($database)], $sqlWhereTable);
418+
$sql = QueryGenerator::getSqlForTablesFull($this->quoteString($database), $sqlWhereTable);
409419

410420
// Sort the tables
411421
$sql .= ' ORDER BY ' . $sortBy . ' ' . $sortOrder;
@@ -504,9 +514,7 @@ static function ($a, $b) {
504514
)
505515
) . ')';
506516
} else {
507-
$sql .= " `Name` LIKE '"
508-
. $this->escapeMysqlLikeString($table, $link)
509-
. "%'";
517+
$sql .= ' `Name` LIKE ' . $this->quoteString($this->escapeMysqlWildcards($table) . '%', $link);
510518
}
511519

512520
$needAnd = true;
@@ -903,7 +911,7 @@ public function getColumn(
903911
$sql = QueryGenerator::getColumnsSql(
904912
$database,
905913
$table,
906-
$this->escapeMysqlLikeString($column),
914+
$this->escapeString($this->escapeMysqlWildcards($column)),
907915
$full
908916
);
909917
/** @var array<string, array> $fields */
@@ -1931,16 +1939,16 @@ public function escapeString(string $str, int $link = self::CONNECT_USER): strin
19311939
}
19321940

19331941
/**
1934-
* returns properly escaped string for use in MySQL LIKE clauses
1942+
* Returns properly escaped string for use in MySQL LIKE clauses.
1943+
* This method escapes only _, %, and /. It does not escape quotes or any other characters.
19351944
*
1936-
* @param string $str string to be escaped
1937-
* @param int $link optional database link to use
1945+
* @param string $str string to be escaped
19381946
*
19391947
* @return string a MySQL escaped LIKE string
19401948
*/
1941-
public function escapeMysqlLikeString(string $str, int $link = self::CONNECT_USER)
1949+
public function escapeMysqlWildcards(string $str): string
19421950
{
1943-
return $this->escapeString(strtr($str, ['\\' => '\\\\', '_' => '\\_', '%' => '\\%']), $link);
1951+
return strtr($str, ['\\' => '\\\\', '_' => '\\_', '%' => '\\%']);
19441952
}
19451953

19461954
/**

libraries/classes/Dbal/DbalInterface.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -605,14 +605,14 @@ public function quoteString(string $str, int $link = DatabaseInterface::CONNECT_
605605
public function escapeString(string $str, int $link = DatabaseInterface::CONNECT_USER): string;
606606

607607
/**
608-
* returns properly escaped string for use in MySQL LIKE clauses
608+
* Returns properly escaped string for use in MySQL LIKE clauses.
609+
* This method escapes only _, %, and /. It does not escape quotes or any other characters.
609610
*
610-
* @param string $str string to be escaped
611-
* @param int $link optional database link to use
611+
* @param string $str string to be escaped
612612
*
613613
* @return string a MySQL escaped LIKE string
614614
*/
615-
public function escapeMysqlLikeString(string $str, int $link = DatabaseInterface::CONNECT_USER);
615+
public function escapeMysqlWildcards(string $str): string;
616616

617617
/**
618618
* Checks if this database server is running on Amazon RDS.

libraries/classes/Html/Generator.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,6 @@ public static function getDbLink($database = ''): string
134134
}
135135

136136
$database = $GLOBALS['db'];
137-
} else {
138-
$database = Util::unescapeMysqlWildcards($database);
139137
}
140138

141139
$scriptName = Util::getScriptNameForOption($GLOBALS['cfg']['DefaultTabDatabase'], 'database');

libraries/classes/ListDatabase.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use function preg_match;
1111
use function sort;
1212
use function strlen;
13+
use function strtr;
1314
use function usort;
1415

1516
/**
@@ -133,7 +134,7 @@ protected function checkOnlyDatabase(): bool
133134
// thus containing not escaped _ or %
134135
if (! preg_match('/(^|[^\\\\])(_|%)/', $each_only_db)) {
135136
// ... not contains wildcard
136-
$items[] = Util::unescapeMysqlWildcards($each_only_db);
137+
$items[] = strtr($each_only_db, ['\\\\' => '\\', '\\_' => '_', '\\%' => '%']);
137138
continue;
138139
}
139140

libraries/classes/Query/Generator.php

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use function array_map;
1010
use function count;
1111
use function implode;
12-
use function is_array;
1312
use function sprintf;
1413

1514
/**
@@ -18,35 +17,50 @@
1817
class Generator
1918
{
2019
/**
21-
* returns a segment of the SQL WHERE clause regarding table name and type
20+
* returns a segment of the SQL WHERE clause regarding table name
2221
*
23-
* @param array|string $escapedTableOrTables table(s)
24-
* @param bool $tblIsGroup $table is a table group
25-
* @param string|null $tableType whether table or view
22+
* @param bool $tblIsGroup $table is a table group
2623
*
2724
* @return string a segment of the WHERE clause
2825
*/
29-
public static function getTableCondition(
30-
$escapedTableOrTables,
31-
bool $tblIsGroup,
32-
?string $tableType
26+
public static function getTableNameCondition(
27+
string $escapedTabletable,
28+
bool $tblIsGroup
3329
): string {
34-
// get table information from information_schema
35-
if ($escapedTableOrTables !== [] && $escapedTableOrTables !== '') {
36-
$sqlWhereTable = 'AND t.`TABLE_NAME` ';
37-
if (is_array($escapedTableOrTables)) {
38-
$sqlWhereTable .= Util::getCollateForIS() . ' IN (\''
39-
. implode('\', \'', $escapedTableOrTables)
40-
. '\')';
41-
} elseif ($tblIsGroup === true) {
42-
$sqlWhereTable .= 'LIKE \'' . Util::escapeMysqlWildcards($escapedTableOrTables) . '%\'';
43-
} else {
44-
$sqlWhereTable .= Util::getCollateForIS() . ' = \'' . $escapedTableOrTables . '\'';
45-
}
30+
$sqlWhereTable = 'AND t.`TABLE_NAME` ';
31+
if ($tblIsGroup === true) {
32+
$sqlWhereTable .= 'LIKE ' . $escapedTabletable . '%';
4633
} else {
47-
$sqlWhereTable = '';
34+
$sqlWhereTable .= Util::getCollateForIS() . ' = ' . $escapedTabletable;
4835
}
4936

37+
return $sqlWhereTable;
38+
}
39+
40+
/**
41+
* returns a segment of the SQL WHERE clause regarding table name
42+
*
43+
* @param string[] $escapedTables tables
44+
*
45+
* @return string a segment of the WHERE clause
46+
*/
47+
public static function getTableNameConditionForMultiple(array $escapedTables): string
48+
{
49+
return 'AND t.`TABLE_NAME` ' . Util::getCollateForIS() . ' IN (' . implode(', ', $escapedTables) . ')';
50+
}
51+
52+
/**
53+
* returns a segment of the SQL WHERE clause regarding table type
54+
*
55+
* @param string|null $tableType whether table or view
56+
*
57+
* @return string a segment of the WHERE clause
58+
*/
59+
public static function getTableTypeCondition(
60+
?string $tableType
61+
): string {
62+
$sqlWhereTable = '';
63+
5064
if ($tableType === 'view') {
5165
$sqlWhereTable .= " AND t.`TABLE_TYPE` NOT IN ('BASE TABLE', 'SYSTEM VERSIONED')";
5266
} elseif ($tableType === 'table') {
@@ -59,12 +73,12 @@ public static function getTableCondition(
5973
/**
6074
* returns the beginning of the SQL statement to fetch the list of tables
6175
*
62-
* @param string[] $thisDatabases databases to list
63-
* @param string $sqlWhereTable additional condition
76+
* @param string $thisDatabases databases to list
77+
* @param string $sqlWhereTable additional condition
6478
*
6579
* @return string the SQL statement
6680
*/
67-
public static function getSqlForTablesFull(array $thisDatabases, string $sqlWhereTable): string
81+
public static function getSqlForTablesFull(string $thisDatabases, string $sqlWhereTable): string
6882
{
6983
return 'SELECT *,'
7084
. ' `TABLE_SCHEMA` AS `Db`,'
@@ -90,7 +104,7 @@ public static function getSqlForTablesFull(array $thisDatabases, string $sqlWher
90104
. ' `TABLE_COMMENT` AS `Comment`'
91105
. ' FROM `information_schema`.`TABLES` t'
92106
. ' WHERE `TABLE_SCHEMA` ' . Util::getCollateForIS()
93-
. ' IN (\'' . implode("', '", $thisDatabases) . '\')'
107+
. ' IN (' . $thisDatabases . ')'
94108
. ' ' . $sqlWhereTable;
95109
}
96110

0 commit comments

Comments
 (0)