Fix Composer autoloader being hijackable by script/plugin event handlers (#11955)
parent
d4396a85bf
commit
bcab1c4b8e
|
@ -180,11 +180,6 @@ parameters:
|
||||||
count: 2
|
count: 2
|
||||||
path: ../src/Composer/Util/Hg.php
|
path: ../src/Composer/Util/Hg.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Only booleans are allowed in &&, int\\<0, 2097152\\> given on the right side\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#1 \\$multi_handle of function curl_multi_add_handle expects CurlMultiHandle, resource\\|null given\\.$#"
|
message: "#^Parameter \\#1 \\$multi_handle of function curl_multi_add_handle expects CurlMultiHandle, resource\\|null given\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
|
@ -332,7 +332,7 @@ parameters:
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||||
count: 4
|
count: 3
|
||||||
path: ../src/Composer/Command/DiagnoseCommand.php
|
path: ../src/Composer/Command/DiagnoseCommand.php
|
||||||
|
|
||||||
-
|
-
|
||||||
|
@ -1850,6 +1850,11 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: ../src/Composer/Downloader/ZipDownloader.php
|
path: ../src/Composer/Downloader/ZipDownloader.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Argument of an invalid type array\\<int, callable\\>\\|false supplied for foreach, only iterables are supported\\.$#"
|
||||||
|
count: 2
|
||||||
|
path: ../src/Composer/EventDispatcher/EventDispatcher.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
@ -4000,7 +4005,7 @@ parameters:
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Cannot access offset 'features' on array\\|false\\.$#"
|
message: "#^Cannot access offset 'features' on array\\|false\\.$#"
|
||||||
count: 2
|
count: 1
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
path: ../src/Composer/Util/Http/CurlDownloader.php
|
||||||
|
|
||||||
-
|
-
|
||||||
|
@ -4010,11 +4015,6 @@ parameters:
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||||
count: 3
|
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Only booleans are allowed in &&, int given on the right side\\.$#"
|
|
||||||
count: 1
|
count: 1
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
path: ../src/Composer/Util/Http/CurlDownloader.php
|
||||||
|
|
||||||
|
@ -4188,11 +4188,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
path: ../src/Composer/Util/Http/CurlDownloader.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method Composer\\\\Util\\\\Http\\\\RequestProxy::getCurlOptions\\(\\) should return array\\<int, int\\|string\\> but returns array\\<int\\|string, int\\|string\\>.$#"
|
|
||||||
count: 1
|
|
||||||
path: ../src/Composer/Util/Http/RequestProxy.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Constant CURLOPT_PROXY_CAINFO not found\\.$#"
|
message: "#^Constant CURLOPT_PROXY_CAINFO not found\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
@ -4203,6 +4198,11 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: ../src/Composer/Util/Http/RequestProxy.php
|
path: ../src/Composer/Util/Http/RequestProxy.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Method Composer\\\\Util\\\\Http\\\\RequestProxy\\:\\:getCurlOptions\\(\\) should return array\\<int, int\\|string\\> but returns array\\<int\\|string, int\\|string\\>\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: ../src/Composer/Util/Http/RequestProxy.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Cannot call method abortRequest\\(\\) on Composer\\\\Util\\\\Http\\\\CurlDownloader\\|null\\.$#"
|
message: "#^Cannot call method abortRequest\\(\\) on Composer\\\\Util\\\\Http\\\\CurlDownloader\\|null\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
@ -4618,11 +4618,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: ../src/Composer/Util/StreamContextFactory.php
|
path: ../src/Composer/Util/StreamContextFactory.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Only booleans are allowed in an if condition, array given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: ../src/Composer/Util/StreamContextFactory.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||||
count: 2
|
count: 2
|
||||||
|
|
|
@ -194,6 +194,8 @@ class EventDispatcher
|
||||||
|
|
||||||
$this->pushEvent($event);
|
$this->pushEvent($event);
|
||||||
|
|
||||||
|
$autoloadersBefore = spl_autoload_functions();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$returnMax = 0;
|
$returnMax = 0;
|
||||||
foreach ($listeners as $callable) {
|
foreach ($listeners as $callable) {
|
||||||
|
@ -411,6 +413,26 @@ class EventDispatcher
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
$this->popEvent();
|
$this->popEvent();
|
||||||
|
|
||||||
|
$knownIdentifiers = [];
|
||||||
|
foreach ($autoloadersBefore as $key => $cb) {
|
||||||
|
$knownIdentifiers[$this->getCallbackIdentifier($cb)] = ['key' => $key, 'callback' => $cb];
|
||||||
|
}
|
||||||
|
foreach (spl_autoload_functions() as $cb) {
|
||||||
|
// once we get to the first known autoloader, we can leave any appended autoloader without problems
|
||||||
|
if (isset($knownIdentifiers[$this->getCallbackIdentifier($cb)]) && $knownIdentifiers[$this->getCallbackIdentifier($cb)]['key'] === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// other newly appeared prepended autoloaders should be appended instead to ensure Composer loads its classes first
|
||||||
|
if ($cb instanceof ClassLoader) {
|
||||||
|
$cb->unregister();
|
||||||
|
$cb->register(false);
|
||||||
|
} else {
|
||||||
|
spl_autoload_unregister($cb);
|
||||||
|
spl_autoload_register($cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $returnMax;
|
return $returnMax;
|
||||||
|
@ -638,4 +660,20 @@ class EventDispatcher
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getCallbackIdentifier(callable $cb): string
|
||||||
|
{
|
||||||
|
if (is_string($cb)) {
|
||||||
|
return 'fn:'.$cb;
|
||||||
|
}
|
||||||
|
if (is_object($cb)) {
|
||||||
|
return 'obj:'.spl_object_hash($cb);
|
||||||
|
}
|
||||||
|
if (is_array($cb)) {
|
||||||
|
return 'array:'.(is_string($cb[0]) ? $cb[0] : get_class($cb[0]) .'#'.spl_object_hash($cb[0])).'::'.$cb[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// not great but also do not want to break everything here
|
||||||
|
return 'unsupported';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue