From 1bf711fe1fcc8d9a7d1f067c06e1fe356cf05bc3 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 19 Apr 2016 15:43:59 +0100 Subject: [PATCH] Guard against mbstring func_overload, fixes #5218 --- src/Composer/Downloader/GzipDownloader.php | 2 +- src/Composer/Util/Platform.php | 18 ++++++++++++++++++ src/Composer/Util/RemoteFilesystem.php | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Composer/Downloader/GzipDownloader.php b/src/Composer/Downloader/GzipDownloader.php index 9969578e5..19e4a45e1 100644 --- a/src/Composer/Downloader/GzipDownloader.php +++ b/src/Composer/Downloader/GzipDownloader.php @@ -76,7 +76,7 @@ class GzipDownloader extends ArchiveDownloader $archiveFile = gzopen($file, 'rb'); $targetFile = fopen($targetFilepath, 'wb'); while ($string = gzread($archiveFile, 4096)) { - fwrite($targetFile, $string, strlen($string)); + fwrite($targetFile, $string, Platform::strlen($string)); } gzclose($archiveFile); fclose($targetFile); diff --git a/src/Composer/Util/Platform.php b/src/Composer/Util/Platform.php index 8939b9467..252041d66 100644 --- a/src/Composer/Util/Platform.php +++ b/src/Composer/Util/Platform.php @@ -26,4 +26,22 @@ class Platform { return defined('PHP_WINDOWS_VERSION_BUILD'); } + + /** + * @param string $str + * @return int return a guaranteed binary length of the string, regardless of silly mbstring configs + */ + public static function strlen($str) + { + static $useMbString = null; + if (null === $useMbString) { + $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload'); + } + + if ($useMbString) { + return mb_strlen($str, '8bit'); + } + + return strlen($str); + } } diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 56d2a2e68..bbdcc3851 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -277,7 +277,7 @@ class RemoteFilesystem try { $result = file_get_contents($fileUrl, false, $ctx); - if ($this->bytesMax && strlen($result) < $this->bytesMax) { + if ($this->bytesMax && Platform::strlen($result) < $this->bytesMax) { // alas, this is not possible via the stream callback because STREAM_NOTIFY_COMPLETED is documented, but not implemented anywhere in PHP throw new TransportException('Content-Length mismatch'); }