Merge pull request #18815 from kamil-tekiela/Fix-ENUM-parsing

Fix enum parsing
This commit is contained in:
Maurício Meneghini Fauth 2023-11-30 08:41:03 -03:00 committed by GitHub
commit ec92177b41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 156 additions and 21 deletions

View File

@ -71,6 +71,7 @@ use function set_time_limit;
use function sort;
use function sprintf;
use function str_contains;
use function str_getcsv;
use function str_pad;
use function str_replace;
use function strcasecmp;
@ -1906,11 +1907,16 @@ class Util
// If you are fixing something here,
// you need to also update the JS port.
preg_match('|\((.*)\)|', $definition, $matches);
// This should really be delegated to MySQL but since we also want to HTML encode it,
// it is easier this way.
// It future replace str_getcsv with $dbi->fetchSingleRow('SELECT '.$expressionInBrackets[1]);
preg_match('/\((.*)\)/', $definition, $expressionInBrackets);
$matches = str_getcsv($expressionInBrackets[1], ',', "'");
$values = [];
foreach (explode(',', $matches[1]) as $value) {
$value = strtr(substr($value, 1, -1), ["''" => "'", "\\'" => "'", '\\\\' => '\\']);
foreach ($matches as $value) {
$value = strtr($value, ['\\\\' => '\\']); // str_getcsv doesn't unescape backslashes so we do it ourselves
$values[] = $escapeHtml ? htmlspecialchars($value, ENT_QUOTES, 'UTF-8') : $value;
}

View File

@ -1635,6 +1635,16 @@ parameters:
count: 1
path: libraries/classes/Controllers/Table/Structure/SaveController.php
-
message: "#^Comparison operation \"\\>\" between int\\<1, max\\> and 0 is always true\\.$#"
count: 1
path: libraries/classes/Controllers/Table/Structure/SaveController.php
-
message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#"
count: 1
path: libraries/classes/Controllers/Table/Structure/SaveController.php
-
message: "#^Method PhpMyAdmin\\\\Controllers\\\\Table\\\\Structure\\\\SaveController\\:\\:adjustColumnPrivileges\\(\\) has parameter \\$adjust_privileges with no value type specified in iterable type array\\.$#"
count: 1
@ -4520,11 +4530,6 @@ parameters:
count: 2
path: libraries/classes/Import.php
-
message: "#^Parameter \\#1 \\$importRunBuffer of method PhpMyAdmin\\\\Import\\:\\:runQueryPost\\(\\) expects array\\|null, array\\|float\\|int\\|string\\|false\\|null given\\.$#"
count: 1
path: libraries/classes/Import.php
-
message: "#^Parameter \\#1 \\$lastCumulativeSize of method PhpMyAdmin\\\\Import\\:\\:getDecimalPrecision\\(\\) expects string, int\\|string given\\.$#"
count: 3
@ -5615,9 +5620,14 @@ parameters:
count: 1
path: libraries/classes/ParseAnalyze.php
-
message: "#^Offset 'select_tables' does not exist on array\\{distinct\\?\\: bool, drop_database\\?\\: bool, group\\?\\: bool, having\\?\\: bool, is_affected\\?\\: bool, is_analyse\\?\\: bool, is_count\\?\\: bool, is_delete\\?\\: bool, \\.\\.\\.\\}\\.$#"
count: 3
path: libraries/classes/ParseAnalyze.php
-
message: "#^Offset 'select_tables' on array\\{distinct\\?\\: bool, drop_database\\?\\: bool, group\\?\\: bool, having\\?\\: bool, is_affected\\?\\: bool, is_analyse\\?\\: bool, is_count\\?\\: bool, is_delete\\?\\: bool, \\.\\.\\.\\} in empty\\(\\) does not exist\\.$#"
count: 1
count: 2
path: libraries/classes/ParseAnalyze.php
-
@ -9030,6 +9040,11 @@ parameters:
count: 1
path: libraries/classes/Util.php
-
message: "#^Parameter \\#1 \\$str of function strtr expects string, string\\|null given\\.$#"
count: 1
path: libraries/classes/Util.php
-
message: "#^Cannot cast mixed to int\\.$#"
count: 1

View File

@ -14248,19 +14248,12 @@
<code>$value</code>
<code>$values['token']</code>
</MixedAssignment>
<MixedInferredReturnType occurrences="1">
<code>string</code>
</MixedInferredReturnType>
<MixedMethodCall occurrences="4">
<code>get</code>
<code>get</code>
<code>getCookie</code>
<code>getCookie</code>
</MixedMethodCall>
<MixedReturnStatement occurrences="2">
<code>$html_separator</code>
<code>$separator</code>
</MixedReturnStatement>
<RedundantCastGivenDocblockType occurrences="2">
<code>(string) $db</code>
<code>(string) $table</code>
@ -14484,9 +14477,10 @@
<code>$sep</code>
<code>$tableGroup</code>
</PossiblyInvalidOperand>
<PossiblyNullArgument occurrences="2">
<PossiblyNullArgument occurrences="3">
<code>$maxSize</code>
<code>$maxUnit</code>
<code>$value</code>
</PossiblyNullArgument>
<PossiblyNullArrayAccess occurrences="2">
<code>$maxSize</code>

View File

@ -63,7 +63,7 @@ class EnumValuesControllerTest extends AbstractTestCase
[
[
'set',
"set('<script>alert(\"ok\")</script>','a&b','b&c','vrai&amp','','漢字','''','\\','\\\"\\\\''')",
"set('<script>alert(\"ok\")</script>','a&b','b&c','vrai&amp','','漢字','''','\\\\','\"\\\\''')",
'No',
'',
'NULL',
@ -110,7 +110,7 @@ class EnumValuesControllerTest extends AbstractTestCase
. ' <option value="漢字">漢字</option>' . "\n"
. ' <option value="&#039;">&#039;</option>' . "\n"
. ' <option value="\">\</option>' . "\n"
. ' <option value="\&quot;\&#039;">\&quot;\&#039;</option>' . "\n"
. ' <option value="&quot;\&#039;">&quot;\&#039;</option>' . "\n"
. ' </select>' . "\n",
],
$this->getResponseJsonResult()

View File

@ -782,7 +782,7 @@ class UtilTest extends AbstractTestCase
'zerofill' => false,
'spec_in_brackets' => "'\'a','b'",
'enum_set_values' => [
"'a",
"\'a",
'b',
],
'attribute' => ' ',
@ -819,7 +819,7 @@ class UtilTest extends AbstractTestCase
'spec_in_brackets' => "'a&b','b''c\\'d','e\\\\f'",
'enum_set_values' => [
'a&b',
'b\'c\'d',
'b\'c\\\'d',
'e\\f',
],
'attribute' => ' ',
@ -890,6 +890,126 @@ class UtilTest extends AbstractTestCase
];
}
/**
* Test case for parsing ENUM values
*
* @param string[] $out
*
* @dataProvider providerParseEnumSetValues
*/
public function testParseEnumSetValues(string $in, bool $escapeHTML, array $out): void
{
$this->assertEquals(
$out,
Util::parseEnumSetValues($in, $escapeHTML)
);
}
/**
* Data provider for testParseEnumSetValues
*
* @return iterable<int, array{string, bool, string[]}>
*/
public function providerParseEnumSetValues(): iterable
{
$enumSpec = "enum('a&b','b''c''d','e\\f')";
yield [
$enumSpec,
false,
[
'a&b',
'b\'c\'d',
'e\\f',
],
];
yield [
$enumSpec,
true,
[
'a&amp;b',
'b&#039;c&#039;d',
'e\\f',
],
];
$enumSpec = "set('<script>alert(\"ok\")</script>','a&b','b&c','vrai&amp','','漢字','''','\\\\','\"\\\\''')";
yield [
$enumSpec,
false,
[
'<script>alert("ok")</script>',
'a&b',
'b&c',
'vrai&amp',
'',
'漢字',
"'",
'\\',
'"\\\'',
],
];
yield [
$enumSpec,
true,
[
'&lt;script&gt;alert(&quot;ok&quot;)&lt;/script&gt;',
'a&amp;b',
'b&amp;c',
'vrai&amp;amp',
'',
'漢字',
'&#039;',
'\\',
'&quot;\&#039;',
],
];
$enumSpec = "enum('1','2,','3''','''4')";
yield [
$enumSpec,
false,
[
'1',
'2,',
'3\'',
'\'4',
],
];
yield [
$enumSpec,
true,
[
'1',
'2,',
'3&#039;',
'&#039;4',
],
];
$enumSpec = "enum('''','''''','\"','\\\\','\\\\''','\\\\\"',',','()')";
yield [
$enumSpec,
false,
[
"'",
"''",
'"',
'\\',
"\\'",
'\\"',
',',
'()',
],
];
}
/**
* Test for Util::extractValueFromFormattedSize
*