MDL-75200 core: function clean_param should work with null - php 8.1

This commit is contained in:
Marina Glancy
2022-09-16 13:30:21 +02:00
parent b077af7e89
commit c2e18d7912
2 changed files with 88 additions and 29 deletions
+29 -28
View File
@@ -844,7 +844,7 @@ function clean_param($param, $type) {
case PARAM_RAW_TRIMMED:
// No cleaning, but strip leading and trailing whitespace.
$param = fix_utf8($param);
$param = (string)fix_utf8($param);
return trim($param);
case PARAM_CLEAN:
@@ -859,7 +859,7 @@ function clean_param($param, $type) {
case PARAM_CLEANHTML:
// Clean html fragment.
$param = fix_utf8($param);
$param = (string)fix_utf8($param);
// Sweep for scripts, etc.
$param = clean_text($param, FORMAT_HTML);
return trim($param);
@@ -878,27 +878,27 @@ function clean_param($param, $type) {
case PARAM_ALPHA:
// Remove everything not `a-z`.
return preg_replace('/[^a-zA-Z]/i', '', $param);
return preg_replace('/[^a-zA-Z]/i', '', (string)$param);
case PARAM_ALPHAEXT:
// Remove everything not `a-zA-Z_-` (originally allowed "/" too).
return preg_replace('/[^a-zA-Z_-]/i', '', $param);
return preg_replace('/[^a-zA-Z_-]/i', '', (string)$param);
case PARAM_ALPHANUM:
// Remove everything not `a-zA-Z0-9`.
return preg_replace('/[^A-Za-z0-9]/i', '', $param);
return preg_replace('/[^A-Za-z0-9]/i', '', (string)$param);
case PARAM_ALPHANUMEXT:
// Remove everything not `a-zA-Z0-9_-`.
return preg_replace('/[^A-Za-z0-9_-]/i', '', $param);
return preg_replace('/[^A-Za-z0-9_-]/i', '', (string)$param);
case PARAM_SEQUENCE:
// Remove everything not `0-9,`.
return preg_replace('/[^0-9,]/i', '', $param);
return preg_replace('/[^0-9,]/i', '', (string)$param);
case PARAM_BOOL:
// Convert to 1 or 0.
$tempstr = strtolower($param);
$tempstr = strtolower((string)$param);
if ($tempstr === 'on' or $tempstr === 'yes' or $tempstr === 'true') {
$param = 1;
} else if ($tempstr === 'off' or $tempstr === 'no' or $tempstr === 'false') {
@@ -911,7 +911,7 @@ function clean_param($param, $type) {
case PARAM_NOTAGS:
// Strip all tags.
$param = fix_utf8($param);
return strip_tags($param);
return strip_tags((string)$param);
case PARAM_TEXT:
// Leave only tags needed for multilang.
@@ -919,7 +919,7 @@ function clean_param($param, $type) {
// If the multilang syntax is not correct we strip all tags because it would break xhtml strict which is required
// for accessibility standards please note this cleaning does not strip unbalanced '>' for BC compatibility reasons.
do {
if (strpos($param, '</lang>') !== false) {
if (strpos((string)$param, '</lang>') !== false) {
// Old and future mutilang syntax.
$param = strip_tags($param, '<lang>');
if (!preg_match_all('/<.*>/suU', $param, $matches)) {
@@ -946,7 +946,7 @@ function clean_param($param, $type) {
}
return $param;
} else if (strpos($param, '</span>') !== false) {
} else if (strpos((string)$param, '</span>') !== false) {
// Current problematic multilang syntax.
$param = strip_tags($param, '<span>');
if (!preg_match_all('/<.*>/suU', $param, $matches)) {
@@ -975,11 +975,12 @@ function clean_param($param, $type) {
}
} while (false);
// Easy, just strip all tags, if we ever want to fix orphaned '&' we have to do that in format_string().
return strip_tags($param);
return strip_tags((string)$param);
case PARAM_COMPONENT:
// We do not want any guessing here, either the name is correct or not
// please note only normalised component names are accepted.
$param = (string)$param;
if (!preg_match('/^[a-z][a-z0-9]*(_[a-z][a-z0-9_]*)?[a-z0-9]+$/', $param)) {
return '';
}
@@ -1004,15 +1005,15 @@ function clean_param($param, $type) {
case PARAM_SAFEDIR:
// Remove everything not a-zA-Z0-9_- .
return preg_replace('/[^a-zA-Z0-9_-]/i', '', $param);
return preg_replace('/[^a-zA-Z0-9_-]/i', '', (string)$param);
case PARAM_SAFEPATH:
// Remove everything not a-zA-Z0-9/_- .
return preg_replace('/[^a-zA-Z0-9\/_-]/i', '', $param);
return preg_replace('/[^a-zA-Z0-9\/_-]/i', '', (string)$param);
case PARAM_FILE:
// Strip all suspicious characters from filename.
$param = fix_utf8($param);
$param = (string)fix_utf8($param);
$param = preg_replace('~[[:cntrl:]]|[&<>"`\|\':\\\\/]~u', '', $param);
if ($param === '.' || $param === '..') {
$param = '';
@@ -1021,7 +1022,7 @@ function clean_param($param, $type) {
case PARAM_PATH:
// Strip all suspicious characters from file path.
$param = fix_utf8($param);
$param = (string)fix_utf8($param);
$param = str_replace('\\', '/', $param);
// Explode the path and clean each element using the PARAM_FILE rules.
@@ -1043,7 +1044,7 @@ function clean_param($param, $type) {
case PARAM_HOST:
// Allow FQDN or IPv4 dotted quad.
$param = preg_replace('/[^\.\d\w-]/', '', $param );
$param = preg_replace('/[^\.\d\w-]/', '', (string)$param );
// Match ipv4 dotted quad.
if (preg_match('/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/', $param, $match)) {
// Confirm values are ok.
@@ -1067,7 +1068,7 @@ function clean_param($param, $type) {
case PARAM_URL:
// Allow safe urls.
$param = fix_utf8($param);
$param = (string)fix_utf8($param);
include_once($CFG->dirroot . '/lib/validateurlsyntax.php');
if (!empty($param) && validateUrlSyntax($param, 's?H?S?F?E-u-P-a?I?p?f?q?r?')) {
// All is ok, param is respected.
@@ -1100,7 +1101,7 @@ function clean_param($param, $type) {
return $param;
case PARAM_PEM:
$param = trim($param);
$param = trim((string)$param);
// PEM formatted strings may contain letters/numbers and the symbols:
// forward slash: /
// plus sign: +
@@ -1148,7 +1149,7 @@ function clean_param($param, $type) {
}
case PARAM_TAG:
$param = fix_utf8($param);
$param = (string)fix_utf8($param);
// Please note it is not safe to use the tag name directly anywhere,
// it must be processed with s(), urlencode() before embedding anywhere.
// Remove some nasties.
@@ -1159,7 +1160,7 @@ function clean_param($param, $type) {
return $param;
case PARAM_TAGLIST:
$param = fix_utf8($param);
$param = (string)fix_utf8($param);
$tags = explode(',', $param);
$result = array();
foreach ($tags as $tag) {
@@ -1222,7 +1223,7 @@ function clean_param($param, $type) {
}
case PARAM_USERNAME:
$param = fix_utf8($param);
$param = (string)fix_utf8($param);
$param = trim($param);
// Convert uppercase to lowercase MDL-16919.
$param = core_text::strtolower($param);
@@ -1236,14 +1237,14 @@ function clean_param($param, $type) {
case PARAM_EMAIL:
$param = fix_utf8($param);
if (validate_email($param)) {
if (validate_email($param ?? '')) {
return $param;
} else {
return '';
}
case PARAM_STRINGID:
if (preg_match('|^[a-zA-Z][a-zA-Z0-9\.:/_-]*$|', $param)) {
if (preg_match('|^[a-zA-Z][a-zA-Z0-9\.:/_-]*$|', (string)$param)) {
return $param;
} else {
return '';
@@ -1251,7 +1252,7 @@ function clean_param($param, $type) {
case PARAM_TIMEZONE:
// Can be int, float(with .5 or .0) or string seperated by '/' and can have '-_'.
$param = fix_utf8($param);
$param = (string)fix_utf8($param);
$timezonepattern = '/^(([+-]?(0?[0-9](\.[5|0])?|1[0-3](\.0)?|1[0-2]\.5))|(99)|[[:alnum:]]+(\/?[[:alpha:]_-])+)$/';
if (preg_match($timezonepattern, $param)) {
return $param;
@@ -1390,7 +1391,7 @@ function get_host_from_url($url) {
* images, objects, etc.
*/
function html_is_blank($string) {
return trim(strip_tags($string, '<img><object><applet><input><select><textarea><hr>')) == '';
return trim(strip_tags((string)$string, '<img><object><applet><input><select><textarea><hr>')) == '';
}
/**
@@ -7333,7 +7334,7 @@ function get_string($identifier, $component = '', $a = null, $lazyload = false)
debugging('extralocations parameter in get_string() is not supported any more, please use standard lang locations only.');
}
if (strpos($component, '/') !== false) {
if (strpos((string)$component, '/') !== false) {
debugging('The module name you passed to get_string is the deprecated format ' .
'like mod/mymod or block/myblock. The correct form looks like mymod, or block_myblock.' , DEBUG_DEVELOPER);
$componentpath = explode('/', $component);
@@ -8802,7 +8803,7 @@ function format_float($float, $decimalpoints=1, $localized=true, $stripzeros=fal
* @return mixed float|bool - false or the parsed float.
*/
function unformat_float($localefloat, $strict = false) {
$localefloat = trim($localefloat);
$localefloat = trim((string)$localefloat);
if ($localefloat == '') {
return null;
+59 -1
View File
@@ -474,32 +474,40 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame(
'#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)',
clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_RAW));
$this->assertSame(null, clean_param(null, PARAM_RAW));
}
public function test_clean_param_trim() {
$this->assertSame('Frog toad', clean_param(" Frog toad \r\n ", PARAM_RAW_TRIMMED));
$this->assertSame('', clean_param(null, PARAM_RAW_TRIMMED));
}
public function test_clean_param_clean() {
// PARAM_CLEAN is an ugly hack, do not use in new code (skodak),
// instead use more specific type, or submit sothing that can be verified properly.
$this->assertSame('xx', clean_param('xx<script>', PARAM_CLEAN));
$this->assertSame('', clean_param(null, PARAM_CLEAN));
$this->assertSame('', clean_param(null, PARAM_CLEANHTML));
}
public function test_clean_param_alpha() {
$this->assertSame('DSFMOSDJ', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHA));
$this->assertSame('', clean_param(null, PARAM_ALPHA));
}
public function test_clean_param_alphanum() {
$this->assertSame('978942897DSFMOSDJ', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHANUM));
$this->assertSame('', clean_param(null, PARAM_ALPHANUM));
}
public function test_clean_param_alphaext() {
$this->assertSame('DSFMOSDJ', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHAEXT));
$this->assertSame('', clean_param(null, PARAM_ALPHAEXT));
}
public function test_clean_param_sequence() {
$this->assertSame(',9789,42897', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_SEQUENCE));
$this->assertSame('', clean_param(null, PARAM_SEQUENCE));
}
public function test_clean_param_component() {
@@ -528,6 +536,7 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame('', clean_param('_user', PARAM_COMPONENT));
$this->assertSame('', clean_param('2rating', PARAM_COMPONENT));
$this->assertSame('', clean_param('user_', PARAM_COMPONENT));
$this->assertSame('', clean_param(null, PARAM_COMPONENT));
}
public function test_clean_param_localisedfloat() {
@@ -544,6 +553,7 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame(false, clean_param('1X000X5', PARAM_LOCALISEDFLOAT));
$this->assertSame(false, clean_param('nan', PARAM_LOCALISEDFLOAT));
$this->assertSame(false, clean_param('10.6blah', PARAM_LOCALISEDFLOAT));
$this->assertSame(null, clean_param(null, PARAM_LOCALISEDFLOAT));
// Tests with a localised decimal separator.
$this->define_local_decimal_separator();
@@ -593,6 +603,7 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame('', clean_param('Xx', PARAM_PLUGIN));
$this->assertSame('', clean_param('_xx', PARAM_PLUGIN));
$this->assertSame('', clean_param('xx_', PARAM_PLUGIN));
$this->assertSame('', clean_param(null, PARAM_PLUGIN));
}
public function test_clean_param_area() {
@@ -609,6 +620,7 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame('', clean_param('some-thing', PARAM_AREA));
$this->assertSame('', clean_param('somethííng', PARAM_AREA));
$this->assertSame('', clean_param('something.x', PARAM_AREA));
$this->assertSame('', clean_param(null, PARAM_AREA));
}
public function test_clean_param_text() {
@@ -630,6 +642,7 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame('<lang lang="en">a>a</lang>', clean_param('<lang lang="en">a>a</lang>', PARAM_TEXT)); // Standard strip_tags() behaviour.
$this->assertSame('a', clean_param('<lang lang="en">a<a</lang>', PARAM_TEXT));
$this->assertSame('<lang lang="en">aa</lang>', clean_param('<lang lang="en">a<br>a</lang>', PARAM_TEXT));
$this->assertSame('', clean_param(null, PARAM_TEXT));
}
public function test_clean_param_url() {
@@ -655,6 +668,7 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame('', clean_param('mailto:[email protected]', PARAM_URL));
$this->assertSame('', clean_param('mailto:[email protected]?subject=Hello%20Moodle', PARAM_URL));
$this->assertSame('', clean_param('mailto:[email protected]?subject=Hello%20Moodle&[email protected]', PARAM_URL));
$this->assertSame('', clean_param(null, PARAM_URL));
}
public function test_clean_param_localurl() {
@@ -695,6 +709,9 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame('', clean_param('http://www.example.com.evil.net/hack.php', PARAM_LOCALURL));
$CFG->wwwroot = 'https://www.example.com';
$this->assertSame('', clean_param('https://www.example.com.evil.net/hack.php', PARAM_LOCALURL));
$this->assertSame('', clean_param('', PARAM_LOCALURL));
$this->assertSame('', clean_param(null, PARAM_LOCALURL));
}
public function test_clean_param_file() {
@@ -719,6 +736,7 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame(' . .dontltrim.me', clean_param(' . .dontltrim.me', PARAM_FILE));
$this->assertSame('here is a tab.txt', clean_param("here is a tab\t.txt", PARAM_FILE));
$this->assertSame('here is a linebreak.txt', clean_param("here is a line\r\nbreak.txt", PARAM_FILE));
$this->assertSame('', clean_param(null, PARAM_FILE));
// The following behaviours have been maintained although they seem a little odd.
$this->assertSame('funnything', clean_param('funny:thing', PARAM_FILE));
@@ -746,6 +764,13 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame('/..b../.../myfile.txt', clean_param('/..b../.../myfile.txt', PARAM_PATH));
$this->assertSame('..b../.../myfile.txt', clean_param('..b../.../myfile.txt', PARAM_PATH));
$this->assertSame('/super/slashes/', clean_param('/super//slashes///', PARAM_PATH));
$this->assertSame('', clean_param(null, PARAM_PATH));
}
public function test_clean_param_safepath() {
$this->assertSame('folder/file', clean_param('folder/file', PARAM_SAFEPATH));
$this->assertSame('folder//file', clean_param('folder/../file', PARAM_SAFEPATH));
$this->assertSame('', clean_param(null, PARAM_SAFEPATH));
}
public function test_clean_param_username() {
@@ -767,6 +792,7 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame(clean_param('john#$%&() ', PARAM_USERNAME), 'john');
$this->assertSame('johnd', clean_param('JOHNdóé ', PARAM_USERNAME));
$this->assertSame(clean_param('john.,:;-_/|\ñÑ[]A_X-,D {} ~!@#$%^&*()_+ ?><[] ščřžžý ?ýáž?žý??šdoe ', PARAM_USERNAME), 'john.-_a_x-d@_doe');
$this->assertSame('', clean_param(null, PARAM_USERNAME));
// Test success condition, if extendedusernamechars == ENABLE;.
$CFG->extendedusernamechars = true;
@@ -796,6 +822,7 @@ class moodlelib_test extends \advanced_testcase {
$this->assertSame('', clean_param('0numeric', PARAM_STRINGID));
$this->assertSame('', clean_param('*', PARAM_STRINGID));
$this->assertSame('', clean_param(' ', PARAM_STRINGID));
$this->assertSame('', clean_param(null, PARAM_STRINGID));
}
public function test_clean_param_timezone() {
@@ -830,7 +857,10 @@ class moodlelib_test extends \advanced_testcase {
'13.5' => '',
'+13.5' => '',
'-13.5' => '',
'0.2' => '');
'0.2' => '',
'' => '',
null => '',
);
foreach ($testvalues as $testvalue => $expectedvalue) {
$actualvalue = clean_param($testvalue, PARAM_TIMEZONE);
@@ -838,6 +868,26 @@ class moodlelib_test extends \advanced_testcase {
}
}
public function test_clean_param_null_argument() {
$this->assertEquals(0, clean_param(null, PARAM_INT));
$this->assertEquals(0, clean_param(null, PARAM_FLOAT));
$this->assertEquals(0, clean_param(null, PARAM_LOCALISEDFLOAT));
$this->assertEquals(false, clean_param(null, PARAM_BOOL));
$this->assertEquals('', clean_param(null, PARAM_NOTAGS));
$this->assertEquals('', clean_param(null, PARAM_SAFEDIR));
$this->assertEquals('', clean_param(null, PARAM_HOST));
$this->assertEquals('', clean_param(null, PARAM_PEM));
$this->assertEquals('', clean_param(null, PARAM_BASE64));
$this->assertEquals('', clean_param(null, PARAM_TAG));
$this->assertEquals('', clean_param(null, PARAM_TAGLIST));
$this->assertEquals('', clean_param(null, PARAM_CAPABILITY));
$this->assertEquals(0, clean_param(null, PARAM_PERMISSION));
$this->assertEquals('', clean_param(null, PARAM_AUTH));
$this->assertEquals('', clean_param(null, PARAM_LANG));
$this->assertEquals('', clean_param(null, PARAM_THEME));
$this->assertEquals('', clean_param(null, PARAM_EMAIL));
}
public function test_validate_param() {
try {
$param = validate_param('11a', PARAM_INT);
@@ -5354,4 +5404,12 @@ EOF;
$default = get_default_home_page();
$this->assertEquals(HOMEPAGE_MYCOURSES, $default);
}
public function test_html_is_blank() {
$this->assertEquals(true, html_is_blank(null));
$this->assertEquals(true, html_is_blank(''));
$this->assertEquals(true, html_is_blank('<p> </p>'));
$this->assertEquals(false, html_is_blank('<p>.</p>'));
$this->assertEquals(false, html_is_blank('<img src="#">'));
}
}