Skip to content

Commit 1ee682d

Browse files
committed
Merge branch 'QA_5_2'
Signed-off-by: Maurício Meneghini Fauth <[email protected]>
2 parents a8f2c77 + 8712d3f commit 1ee682d

File tree

13 files changed

+107
-46
lines changed

13 files changed

+107
-46
lines changed

ChangeLog

+10-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,16 @@ phpMyAdmin - ChangeLog
1818
- issue #17480 Added an option in the SQL box to "Format as a single line"
1919
- issue Add support for `INSERT IGNORE` into for non table imports
2020

21-
5.2.2 (not yet released)
21+
5.2.3 (not yet released)
22+
- issue #19548 Fix missing tooltip in status monitor log table
23+
24+
5.2.2 (2025-01-21)
25+
- issue [security] Fix for a path disclosure leak in the Monitoring tab
26+
- issue Prevent the user from deleting system databases
27+
- issue [security] Fix an XSS vulnerability when checking tables (PMASA-2025-1)
28+
- issue [security] Fix an XSS vulnerability on the Insert tab (PMASA-2025-2)
29+
- issue [security] Fix a possible glibc/iconv vulnerability (CVE-2024-2961, assigned PMASA-2025-3 but please note that phpMyAdmin is not vulnerable by default)
30+
- issue Fix for sql-parser relating to quadratic complexity in certain queries, which could have caused long execution times.
2231
- issue #17851 Fix total count of rows in not accurate
2332
- issue #17766 Allow to open in a new tab copy and edit row actions
2433
- issue #17599 Fix error when handling an user that is not in privileges table

phpstan-baseline.neon

+7-19
Original file line numberDiff line numberDiff line change
@@ -3234,24 +3234,6 @@ parameters:
32343234
count: 1
32353235
path: src/Controllers/Server/Databases/DestroyController.php
32363236

3237-
-
3238-
message: '#^Parameter \#1 \$db of method PhpMyAdmin\\ConfigStorage\\RelationCleanup\:\:database\(\) expects string, mixed given\.$#'
3239-
identifier: argument.type
3240-
count: 1
3241-
path: src/Controllers/Server/Databases/DestroyController.php
3242-
3243-
-
3244-
message: '#^Parameter \#1 \$db of method PhpMyAdmin\\Transformations\:\:clear\(\) expects string, mixed given\.$#'
3245-
identifier: argument.type
3246-
count: 1
3247-
path: src/Controllers/Server/Databases/DestroyController.php
3248-
3249-
-
3250-
message: '#^Parameter \#1 \$identifier of static method PhpMyAdmin\\Util\:\:backquote\(\) expects string\|Stringable\|null, mixed given\.$#'
3251-
identifier: argument.type
3252-
count: 1
3253-
path: src/Controllers/Server/Databases/DestroyController.php
3254-
32553237
-
32563238
message: '''
32573239
#^Call to deprecated method getInstance\(\) of class PhpMyAdmin\\Config\:
@@ -6975,6 +6957,12 @@ parameters:
69756957
count: 2
69766958
path: src/Encoding.php
69776959

6960+
-
6961+
message: '#^Right side of && is always true\.$#'
6962+
identifier: booleanAnd.rightAlwaysTrue
6963+
count: 1
6964+
path: src/Encoding.php
6965+
69786966
-
69796967
message: '#^Static property PhpMyAdmin\\Encoding\:\:\$engine \(int\|null\) does not accept mixed\.$#'
69806968
identifier: assign.propertyType
@@ -19152,7 +19140,7 @@ parameters:
1915219140
Use dependency injection instead\.$#
1915319141
'''
1915419142
identifier: staticMethod.deprecated
19155-
count: 2
19143+
count: 3
1915619144
path: tests/unit/EncodingTest.php
1915719145

1915819146
-

psalm-baseline.xml

+7-4
Original file line numberDiff line numberDiff line change
@@ -1897,11 +1897,8 @@
18971897
<DeprecatedMethod>
18981898
<code><![CDATA[Config::getInstance()]]></code>
18991899
</DeprecatedMethod>
1900-
<MixedArgument>
1901-
<code><![CDATA[$database]]></code>
1902-
</MixedArgument>
19031900
<MixedAssignment>
1904-
<code><![CDATA[$database]]></code>
1901+
<code><![CDATA[$selectedDbs]]></code>
19051902
</MixedAssignment>
19061903
<PossiblyUnusedReturnValue>
19071904
<code><![CDATA[Response]]></code>
@@ -4410,6 +4407,11 @@
44104407
<PossiblyUnusedMethod>
44114408
<code><![CDATA[setKanjiEncodings]]></code>
44124409
</PossiblyUnusedMethod>
4410+
<RedundantConditionGivenDocblockType>
4411+
<code><![CDATA[is_string($config->settings['IconvExtraParams'])]]></code>
4412+
<code><![CDATA[isset($config->settings['IconvExtraParams'])
4413+
&& is_string($config->settings['IconvExtraParams'])]]></code>
4414+
</RedundantConditionGivenDocblockType>
44134415
</file>
44144416
<file src="src/Engines/Innodb.php">
44154417
<DeprecatedMethod>
@@ -11469,6 +11471,7 @@
1146911471
<DeprecatedMethod>
1147011472
<code><![CDATA[Config::getInstance()]]></code>
1147111473
<code><![CDATA[Config::getInstance()]]></code>
11474+
<code><![CDATA[Config::getInstance()]]></code>
1147211475
</DeprecatedMethod>
1147311476
</file>
1147411477
<file src="tests/unit/Engines/PbxtTest.php">

resources/js/src/server/status/monitor.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -2142,15 +2142,16 @@ AJAX.registerOnload('server/status/monitor.js', function () {
21422142
'</span></th><th class="text-end">' + data.sum.TOTAL + '</th></tr></tfoot>');
21432143

21442144
// Append a tooltip to the count column, if there exist one
2145-
if ($('#logTable').find('tr').first().find('th').last().text().indexOf('#') > -1) {
2146-
$('#logTable').find('tr').first().find('th').last().append('&nbsp;' + getImageTag('b_help', '', { 'class': 'qroupedQueryInfoIcon' }));
2145+
const amountColumn = $('#logTable').find('tr').first().find('th').last();
2146+
if (amountColumn.text().indexOf('#') > -1) {
2147+
amountColumn.append('&nbsp;' + getImageTag('b_help'));
21472148

2148-
var tooltipContent = window.Messages.strCountColumnExplanation;
2149+
let tooltipContent = window.Messages.strCountColumnExplanation;
21492150
if (groupInserts) {
2150-
tooltipContent += '<p>' + window.Messages.strMoreCountColumnExplanation + '</p>';
2151+
tooltipContent += '<br>' + window.Messages.strMoreCountColumnExplanation;
21512152
}
21522153

2153-
tooltip($('img.qroupedQueryInfoIcon'), 'img', tooltipContent);
2154+
tooltip(amountColumn, 'th', tooltipContent);
21542155
}
21552156

21562157
$('#logTable').find('table').tablesorter({

src/Controllers/Export/ExportController.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ public function __invoke(ServerRequest $request): Response
225225
// Do we need to convert charset?
226226
Export::$outputCharsetConversion = Export::$asFile
227227
&& Encoding::isSupported()
228-
&& isset(Current::$charset) && Current::$charset !== 'utf-8';
228+
&& isset(Current::$charset) && Current::$charset !== 'utf-8'
229+
&& in_array(Current::$charset, Encoding::listEncodings(), true);
229230

230231
// Use on the fly compression?
231232
Export::$onFlyCompression = $config->settings['CompressOnFly'] && Export::$compression === 'gzip';

src/Controllers/Import/ImportController.php

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
use function __;
3535
use function _ngettext;
36+
use function in_array;
3637
use function ini_get;
3738
use function ini_parse_quantity;
3839
use function ini_set;
@@ -444,6 +445,7 @@ public function __invoke(ServerRequest $request): Response
444445
if (
445446
Encoding::isSupported()
446447
&& ImportSettings::$charsetOfFile !== '' && ImportSettings::$charsetOfFile !== 'utf-8'
448+
&& in_array(ImportSettings::$charsetOfFile, Encoding::listEncodings(), true)
447449
) {
448450
ImportSettings::$charsetConversion = true;
449451
} elseif (ImportSettings::$charsetOfFile !== '' && ImportSettings::$charsetOfFile !== 'utf-8') {

src/Controllers/Server/Databases/DestroyController.php

+14-7
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,18 @@
1111
use PhpMyAdmin\Http\Response;
1212
use PhpMyAdmin\Http\ServerRequest;
1313
use PhpMyAdmin\Message;
14+
use PhpMyAdmin\Query\Utilities;
1415
use PhpMyAdmin\ResponseRenderer;
1516
use PhpMyAdmin\Transformations;
1617
use PhpMyAdmin\UserPrivilegesFactory;
1718
use PhpMyAdmin\Util;
1819

1920
use function __;
2021
use function _ngettext;
22+
use function array_filter;
2123
use function count;
2224
use function is_array;
25+
use function is_string;
2326

2427
final class DestroyController implements InvocableController
2528
{
@@ -36,11 +39,10 @@ public function __invoke(ServerRequest $request): Response
3639
{
3740
$userPrivileges = $this->userPrivilegesFactory->getPrivileges();
3841

39-
$selectedDbs = $request->getParsedBodyParam('selected_dbs');
40-
42+
$config = Config::getInstance();
4143
if (
4244
! $request->isAjax()
43-
|| (! $this->dbi->isSuperUser() && ! Config::getInstance()->settings['AllowUserDropDatabase'])
45+
|| (! $this->dbi->isSuperUser() && ! $config->settings['AllowUserDropDatabase'])
4446
) {
4547
$message = Message::error();
4648
$json = ['message' => $message];
@@ -50,10 +52,15 @@ public function __invoke(ServerRequest $request): Response
5052
return $this->response->response();
5153
}
5254

53-
if (
54-
! is_array($selectedDbs)
55-
|| $selectedDbs === []
56-
) {
55+
$selectedDbs = $request->getParsedBodyParam('selected_dbs');
56+
$selectedDbs = is_array($selectedDbs) ? $selectedDbs : [];
57+
$selectedDbs = array_filter($selectedDbs, static function ($database) use ($config): bool {
58+
return is_string($database)
59+
&& ! Utilities::isSystemSchema($database, true)
60+
&& $database !== ($config->selectedServer['pmadb'] ?? '');
61+
});
62+
63+
if ($selectedDbs === []) {
5764
$message = Message::error(__('No databases selected.'));
5865
$json = ['message' => $message];
5966
$this->response->setRequestStatus($message->isSuccess());

src/Encoding.php

+25-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpMyAdmin;
66

7+
use function array_filter;
78
use function array_intersect;
89
use function array_map;
910
use function explode;
@@ -14,11 +15,16 @@
1415
use function function_exists;
1516
use function fwrite;
1617
use function iconv;
18+
use function is_string;
1719
use function mb_convert_encoding;
1820
use function mb_convert_kana;
1921
use function mb_detect_encoding;
2022
use function mb_list_encodings;
23+
use function preg_replace;
24+
use function str_contains;
25+
use function str_starts_with;
2126
use function strtolower;
27+
use function strtoupper;
2228
use function tempnam;
2329
use function unlink;
2430

@@ -156,11 +162,18 @@ public static function convertString(
156162
self::initEngine();
157163
}
158164

165+
$config = Config::getInstance();
166+
$iconvExtraParams = '';
167+
if (
168+
isset($config->settings['IconvExtraParams'])
169+
&& is_string($config->settings['IconvExtraParams'])
170+
&& str_starts_with($config->settings['IconvExtraParams'], '//')
171+
) {
172+
$iconvExtraParams = $config->settings['IconvExtraParams'];
173+
}
174+
159175
return match (self::$engine) {
160-
self::ENGINE_ICONV => iconv(
161-
$srcCharset,
162-
$destCharset . (Config::getInstance()->settings['IconvExtraParams'] ?? ''), $what,
163-
),
176+
self::ENGINE_ICONV => iconv($srcCharset, $destCharset . $iconvExtraParams, $what),
164177
self::ENGINE_MB => mb_convert_encoding($what, $destCharset, $srcCharset),
165178
default => $what,
166179
};
@@ -310,7 +323,14 @@ public static function listEncodings(): array
310323
/* Most engines do not support listing */
311324
$config = Config::getInstance();
312325
if (self::$engine != self::ENGINE_MB) {
313-
return $config->settings['AvailableCharsets'];
326+
return array_filter($config->settings['AvailableCharsets'], static function (string $charset): bool {
327+
// Removes any ignored character
328+
$normalizedCharset = strtoupper((string) preg_replace(['/[^A-Za-z0-9\-\/]/'], '', $charset));
329+
330+
// The character set ISO-2022-CN-EXT can be vulnerable (CVE-2024-2961).
331+
return ! str_contains($normalizedCharset, 'ISO-2022-CN-EXT')
332+
&& ! str_contains($normalizedCharset, 'ISO2022CNEXT');
333+
});
314334
}
315335

316336
return array_intersect(

src/Error/ErrorHandler.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,13 @@ public function handleError(
236236
public function handleException(Throwable $exception): void
237237
{
238238
$this->hideLocation = Config::getInstance()->get('environment') !== 'development';
239+
$message = $exception::class;
240+
if (! ($exception instanceof \Error) || ! $this->hideLocation) {
241+
$message .= ': ' . $exception->getMessage();
242+
}
243+
239244
$this->addError(
240-
$exception::class . ': ' . $exception->getMessage(),
245+
$message,
241246
(int) $exception->getCode(),
242247
$exception->getFile(),
243248
$exception->getLine(),

src/InsertEdit.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ private function getSpecialCharsForInsertingMode(
782782
$specialChars = bin2hex($defaultValue);
783783
} elseif (str_ends_with($trueType, 'text')) {
784784
$textDefault = substr($defaultValue, 1, -1);
785-
$specialChars = stripcslashes($textDefault !== '' ? $textDefault : $defaultValue);
785+
$specialChars = htmlspecialchars(stripcslashes($textDefault !== '' ? $textDefault : $defaultValue));
786786
} else {
787787
$specialChars = htmlspecialchars($defaultValue);
788788
}

src/Table/Maintenance.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use PhpMyAdmin\Util;
1414

1515
use function __;
16+
use function htmlspecialchars;
1617
use function implode;
1718
use function sprintf;
1819

@@ -113,7 +114,7 @@ public function getIndexesProblems(DatabaseName $db, array $tables): string
113114
continue;
114115
}
115116

116-
$indexesProblems .= sprintf(__('Problems with indexes of table `%s`'), $table->getName());
117+
$indexesProblems .= htmlspecialchars(sprintf(__('Problems with indexes of table `%s`'), $table->getName()));
117118
$indexesProblems .= $check;
118119
}
119120

tests/unit/EncodingTest.php

+19
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,23 @@ public function testListEncodings(): void
197197
$result = Encoding::listEncodings();
198198
self::assertContains('utf-8', $result);
199199
}
200+
201+
public function testListEncodingsForIso2022CnExt(): void
202+
{
203+
Encoding::setEngine(Encoding::ENGINE_ICONV);
204+
Config::getInstance()->settings['AvailableCharsets'] = [
205+
'utf-8',
206+
'ISO-2022-CN',
207+
'ISO2022CN',
208+
'ISO-2022-CN-EXT',
209+
'ISO2022CNEXT',
210+
' iso-2022-cn-ext ',
211+
'ISO-2022-CN-EXT//TRANSLIT',
212+
' I S O - 2 0 2 2 - C N - E X T ',
213+
' I S O 2 0 2 2 C N E X T ',
214+
'IS%O-20(22-CN-E$XT',
215+
];
216+
217+
self::assertSame(['utf-8', 'ISO-2022-CN', 'ISO2022CN'], Encoding::listEncodings());
218+
}
200219
}

tests/unit/InsertEditTest.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -1248,13 +1248,18 @@ public static function providerForTestGetSpecialCharsForInsertingMode(): array
12481248
'any text with escape text default' => [
12491249
'"lorem\"ipsem"',
12501250
'text',
1251-
'lorem"ipsem',
1251+
'lorem&quot;ipsem',
12521252
],
12531253
'varchar with html special chars' => [
12541254
'hello world<br><b>lorem</b> ipsem',
12551255
'varchar',
12561256
'hello world&lt;br&gt;&lt;b&gt;lorem&lt;/b&gt; ipsem',
12571257
],
1258+
'text with html special chars' => [
1259+
'\'</textarea><script>alert(1)</script>\'',
1260+
'text',
1261+
'&lt;/textarea&gt;&lt;script&gt;alert(1)&lt;/script&gt;',
1262+
],
12581263
];
12591264
}
12601265

0 commit comments

Comments
 (0)