From fc2abc1203fff4c5cf194b1bb462b2a4cd946ced Mon Sep 17 00:00:00 2001 From: "J. King" Date: Thu, 24 Jun 2021 11:58:50 -0400 Subject: [PATCH] Use D modifier for all patterns with $ anchors --- RoboFile.php | 12 ++++++------ lib/Db/MySQL/Driver.php | 2 +- lib/Misc/HTTP.php | 2 +- lib/Misc/URL.php | 2 +- lib/Misc/ValueInfo.php | 4 ++-- lib/REST.php | 6 +++--- lib/REST/Miniflux/V1.php | 2 +- lib/REST/NextcloudNews/Versions.php | 2 +- lib/REST/TinyTinyRSS/API.php | 2 +- lib/REST/TinyTinyRSS/Icon.php | 2 +- tests/cases/Db/MySQL/TestStatement.php | 2 +- tests/cases/Db/MySQLPDO/TestStatement.php | 2 +- tests/cases/Db/PostgreSQL/TestStatement.php | 2 +- tests/cases/Db/PostgreSQLPDO/TestStatement.php | 2 +- 14 files changed, 22 insertions(+), 22 deletions(-) diff --git a/RoboFile.php b/RoboFile.php index ee4c74ac..e2ea42a1 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -218,7 +218,7 @@ class RoboFile extends \Robo\Tasks { // Remove files which lintian complains about; they're otherwise harmless $files = []; foreach (new \CallbackFilterIterator(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir."vendor", \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS)), function($v, $k, $i) { - return preg_match('/\/\.git(?:ignore|attributes|modules)$/', $v); + return preg_match('/\/\.git(?:ignore|attributes|modules)$/D', $v); }) as $f) { $files[] = $f; } @@ -356,9 +356,9 @@ class RoboFile extends \Robo\Tasks { $expected = ["version"]; for ($a = 0; $a < sizeof($lines);) { $l = rtrim($lines[$a++]); - if (in_array("version", $expected) && preg_match('/^Version (\d+(?:\.\d+)*) \(([\d\?]{4}-[\d\?]{2}-[\d\?]{2})\)\s*$/', $l, $m)) { + if (in_array("version", $expected) && preg_match('/^Version (\d+(?:\.\d+)*) \(([\d\?]{4}-[\d\?]{2}-[\d\?]{2})\)\s*$/D', $l, $m)) { $version = $m[1]; - if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $m[2])) { + if (!preg_match('/^\d{4}-\d{2}-\d{2}$/D', $m[2])) { // uncertain dates are allowed only for the top version, and only if it does not match the target version (otherwise we have forgotten to set the correct date before tagging) if (!$out && $targetVersion !== $version) { // use today's date; local time is fine @@ -398,10 +398,10 @@ class RoboFile extends \Robo\Tasks { } elseif (in_array("changes section", $expected) && $l === "Changes:") { $section = "changes"; $expected = ["item"]; - } elseif (in_array("item", $expected) && preg_match('/^- (\w.*)$/', $l, $m)) { + } elseif (in_array("item", $expected) && preg_match('/^- (\w.*)$/D', $l, $m)) { $entry[$section][] = $m[1]; $expected = ["item", "continuation", "blank line"]; - } elseif (in_array("continuation", $expected) && preg_match('/^ (\w.*)$/', $l, $m)) { + } elseif (in_array("continuation", $expected) && preg_match('/^ (\w.*)$/D', $l, $m)) { $last = sizeof($entry[$section]) - 1; $entry[$section][$last] .= "\n".$m[1]; } else { @@ -436,7 +436,7 @@ class RoboFile extends \Robo\Tasks { $out = ""; foreach ($log as $entry) { // normalize the version string - preg_match('/^(\d+(?:\.\d+)*)(?:-(\d+)-.+)?$/', $entry['version'], $m); + preg_match('/^(\d+(?:\.\d+)*)(?:-(\d+)-.+)?$/D', $entry['version'], $m); $version = $m[1]."-".($m[2] ?: "1"); // output the entry $out .= "arsse ($version) UNRELEASED; urgency=low\n"; diff --git a/lib/Db/MySQL/Driver.php b/lib/Db/MySQL/Driver.php index d2c538bc..9acd1eaa 100644 --- a/lib/Db/MySQL/Driver.php +++ b/lib/Db/MySQL/Driver.php @@ -224,7 +224,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { // with MySQL each table must be analyzed separately, so we first have to get a list of tables foreach ($this->query("SHOW TABLES like 'arsse\\_%'") as $table) { $table = array_pop($table); - if (!preg_match("/^arsse_[a-z_]+$/", $table)) { + if (!preg_match("/^arsse_[a-z_]+$/D", $table)) { // table is not one of ours continue; // @codeCoverageIgnore } diff --git a/lib/Misc/HTTP.php b/lib/Misc/HTTP.php index 15bfce9b..ac415062 100644 --- a/lib/Misc/HTTP.php +++ b/lib/Misc/HTTP.php @@ -12,7 +12,7 @@ class HTTP { public static function matchType(MessageInterface $msg, string ...$type): bool { $header = $msg->getHeaderLine("Content-Type") ?? ""; foreach ($type as $t) { - $pattern = "/^".preg_quote(trim($t), "/")."\s*($|;|,)/i"; + $pattern = "/^".preg_quote(trim($t), "/")."\s*($|;|,)/Di"; if (preg_match($pattern, $header)) { return true; } diff --git a/lib/Misc/URL.php b/lib/Misc/URL.php index df16e6fd..a1cad01b 100644 --- a/lib/Misc/URL.php +++ b/lib/Misc/URL.php @@ -78,7 +78,7 @@ class URL { if ($c === "%") { // the % character signals an encoded character... $d = substr($part, $pos + 1, 2); - if (!preg_match("/^[0-9a-fA-F]{2}$/", $d)) { + if (!preg_match("/^[0-9a-fA-F]{2}$/D", $d)) { // unless there are fewer than two characters left in the string or the two characters are not hex digits $d = ord($c); } else { diff --git a/lib/Misc/ValueInfo.php b/lib/Misc/ValueInfo.php index 688a394b..0aba7700 100644 --- a/lib/Misc/ValueInfo.php +++ b/lib/Misc/ValueInfo.php @@ -222,7 +222,7 @@ class ValueInfo { return $out; } else { $out = sprintf("%F", $value); - return preg_match("/\.0{1,}$/", $out) ? (string) (int) $out : $out; + return preg_match("/\.0{1,}$/D", $out) ? (string) (int) $out : $out; } } $info = self::str($value); @@ -256,7 +256,7 @@ class ValueInfo { $out = false; if ($dateInFormat === "microtime") { // PHP is not able to correctly handle the output of microtime() as the input of DateTime::createFromFormat(), so we fudge it to look like a float - if (preg_match("<^0\.\d{6}00 \d+$>", $value)) { + if (preg_match("<^0\.\d{6}00 \d+$>D", $value)) { $value = substr($value, 11).".".substr($value, 2, 6); } else { throw new \Exception; diff --git a/lib/REST.php b/lib/REST.php index 15522773..8d26628e 100644 --- a/lib/REST.php +++ b/lib/REST.php @@ -118,7 +118,7 @@ class REST { // first try a simple substring match if (strpos($url, $api['match']) === 0) { // if it matches, perform a more rigorous match and then strip off any defined prefix - $pattern = "<^".preg_quote($api['match'])."([/\?#]|$)>"; + $pattern = "<^".preg_quote($api['match'])."([/\?#]|$)>D"; if ($url === $api['match'] || in_array(substr($api['match'], -1, 1), ["/", "?", "#"]) || preg_match($pattern, $url)) { $target = substr($url, strlen($api['strip'])); } else { @@ -258,7 +258,7 @@ class REST { // if the origin is the special value "null", use it return "null"; } - if (preg_match("<^([^:]+)://(\[[^\]]+\]|[^\[\]:/\?#@]+)((?::.*)?)$>i", $origin, $match)) { + if (preg_match("<^([^:]+)://(\[[^\]]+\]|[^\[\]:/\?#@]+)((?::.*)?)$>Di", $origin, $match)) { // if the origin sort-of matches the syntax in a general sense, continue $scheme = $match[1]; $host = $match[2]; @@ -266,7 +266,7 @@ class REST { // decode and normalize the scheme and port (the port may be blank) $scheme = strtolower(rawurldecode($scheme)); $port = rawurldecode($port); - if (!preg_match("<^(?::[0-9]+)?$>", $port) || !preg_match("<^[a-z](?:[a-z0-9\+\-\.])*$>", $scheme)) { + if (!preg_match("<^(?::[0-9]+)?$>D", $port) || !preg_match("<^[a-z](?:[a-z0-9\+\-\.])*$>D", $scheme)) { // if the normalized port contains anything but numbers, or the scheme does not follow the generic URL syntax, the origin is invalid return ""; } diff --git a/lib/REST/Miniflux/V1.php b/lib/REST/Miniflux/V1.php index 4c55fbc6..7cba4061 100644 --- a/lib/REST/Miniflux/V1.php +++ b/lib/REST/Miniflux/V1.php @@ -332,7 +332,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler { } } // handle special case "Get User By User Name", which can have any non-numeric string, non-empty as the last component - if (sizeof($path) === 3 && $path[0] === "" && $path[1] === "users" && !preg_match("/^(?:\d+)?$/", $path[2])) { + if (sizeof($path) === 3 && $path[0] === "" && $path[1] === "users" && !preg_match("/^(?:\d+)?$/D", $path[2])) { $path[2] = "*"; } return implode("/", $path); diff --git a/lib/REST/NextcloudNews/Versions.php b/lib/REST/NextcloudNews/Versions.php index 8337736b..95ee0bf3 100644 --- a/lib/REST/NextcloudNews/Versions.php +++ b/lib/REST/NextcloudNews/Versions.php @@ -16,7 +16,7 @@ class Versions implements \JKingWeb\Arsse\REST\Handler { } public function dispatch(ServerRequestInterface $req): ResponseInterface { - if (!preg_match("<^/?$>", $req->getRequestTarget())) { + if (!preg_match("<^/?$>D", $req->getRequestTarget())) { // if the request path is more than an empty string or a slash, the client is probably trying a version we don't support return new EmptyResponse(404); } diff --git a/lib/REST/TinyTinyRSS/API.php b/lib/REST/TinyTinyRSS/API.php index 60c4e3bb..74f315a5 100644 --- a/lib/REST/TinyTinyRSS/API.php +++ b/lib/REST/TinyTinyRSS/API.php @@ -94,7 +94,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { } public function dispatch(ServerRequestInterface $req): ResponseInterface { - if (!preg_match("<^(?:/(?:index\.php)?)?$>", $req->getRequestTarget())) { + if (!preg_match("<^(?:/(?:index\.php)?)?$>D", $req->getRequestTarget())) { // reject paths other than the index return new EmptyResponse(404); } diff --git a/lib/REST/TinyTinyRSS/Icon.php b/lib/REST/TinyTinyRSS/Icon.php index 9e7c7ec0..dd718bcb 100644 --- a/lib/REST/TinyTinyRSS/Icon.php +++ b/lib/REST/TinyTinyRSS/Icon.php @@ -27,7 +27,7 @@ class Icon extends \JKingWeb\Arsse\REST\AbstractHandler { if ($req->getMethod() !== "GET") { // only GET requests are allowed return new Response(405, ['Allow' => "GET"]); - } elseif (!preg_match("<^(\d+)\.ico$>", $req->getRequestTarget(), $match) || !((int) $match[1])) { + } elseif (!preg_match("<^(\d+)\.ico$>D", $req->getRequestTarget(), $match) || !((int) $match[1])) { return new Response(404); } try { diff --git a/tests/cases/Db/MySQL/TestStatement.php b/tests/cases/Db/MySQL/TestStatement.php index 76c7b819..59b0177f 100644 --- a/tests/cases/Db/MySQL/TestStatement.php +++ b/tests/cases/Db/MySQL/TestStatement.php @@ -23,7 +23,7 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement { case "float": return (substr($value, -2) === ".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'"; case "string": - if (preg_match("<^char\((\d+)\)$>", $value, $match)) { + if (preg_match("<^char\((\d+)\)$>D", $value, $match)) { return "'".\IntlChar::chr((int) $match[1])."'"; } return $value; diff --git a/tests/cases/Db/MySQLPDO/TestStatement.php b/tests/cases/Db/MySQLPDO/TestStatement.php index a6d0706e..678300c1 100644 --- a/tests/cases/Db/MySQLPDO/TestStatement.php +++ b/tests/cases/Db/MySQLPDO/TestStatement.php @@ -24,7 +24,7 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement { case "float": return (substr($value, -2) === ".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'"; case "string": - if (preg_match("<^char\((\d+)\)$>", $value, $match)) { + if (preg_match("<^char\((\d+)\)$>D", $value, $match)) { return "'".\IntlChar::chr((int) $match[1])."'"; } return $value; diff --git a/tests/cases/Db/PostgreSQL/TestStatement.php b/tests/cases/Db/PostgreSQL/TestStatement.php index 8ec5fdbb..c4ecefad 100644 --- a/tests/cases/Db/PostgreSQL/TestStatement.php +++ b/tests/cases/Db/PostgreSQL/TestStatement.php @@ -23,7 +23,7 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement { case "float": return (substr($value, -2) === ".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'"; case "string": - if (preg_match("<^char\((\d+)\)$>", $value, $match)) { + if (preg_match("<^char\((\d+)\)$>D", $value, $match)) { return "U&'\\+".str_pad(dechex((int) $match[1]), 6, "0", \STR_PAD_LEFT)."'"; } return $value; diff --git a/tests/cases/Db/PostgreSQLPDO/TestStatement.php b/tests/cases/Db/PostgreSQLPDO/TestStatement.php index 8878d421..89bae7d9 100644 --- a/tests/cases/Db/PostgreSQLPDO/TestStatement.php +++ b/tests/cases/Db/PostgreSQLPDO/TestStatement.php @@ -23,7 +23,7 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement { case "float": return (substr($value, -2) === ".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'"; case "string": - if (preg_match("<^char\((\d+)\)$>", $value, $match)) { + if (preg_match("<^char\((\d+)\)$>D", $value, $match)) { return "U&'\\+".str_pad(dechex((int) $match[1]), 6, "0", \STR_PAD_LEFT)."'"; } return $value;