From c2d99608988e7892a4c67f0c57c0fdb68de2d4b1 Mon Sep 17 00:00:00 2001 From: Niels Keurentjes Date: Sat, 6 Feb 2016 02:00:54 +0100 Subject: [PATCH 1/5] Ensure exception is thrown when classmaps are requested for corrupted or binary files. Refs #4885 --- src/Composer/Autoload/ClassMapGenerator.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index 3f1243ade..539eb77a0 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -123,14 +123,14 @@ class ClassMapGenerator } try { - $contents = Silencer::call('php_strip_whitespace', $path); + $contents = @php_strip_whitespace($path); if (!$contents) { if (!file_exists($path)) { - throw new \Exception('File does not exist'); - } - if (!is_readable($path)) { - throw new \Exception('File is not readable'); + throw new \RuntimeException(sprintf('File at "%s" does not exist, check your classmap definitions', $path)); + } elseif (!is_readable($path)) { + throw new \RuntimeException(sprintf('File at "%s" is not readable, check its permissions', $path)); } + throw new \RuntimeException(sprintf('File at "%s" could not be parsed as PHP - it may be binary or corrupted', $path)); } } catch (\Exception $e) { throw new \RuntimeException('Could not scan for classes inside '.$path.": \n".$e->getMessage(), 0, $e); From 86fc85fe56c0cb8336c9628fd719c0134360f27b Mon Sep 17 00:00:00 2001 From: Niels Keurentjes Date: Sat, 6 Feb 2016 02:04:48 +0100 Subject: [PATCH 2/5] Add a comment explaining the use of @ instead of Silencer in this specific situation. --- src/Composer/Autoload/ClassMapGenerator.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index 539eb77a0..3ad26f7f2 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -123,6 +123,8 @@ class ClassMapGenerator } try { + // Use @ here instead of Silencer to actively suppress 'unhelpful' output + // @link https://github.com/composer/composer/pull/4886 $contents = @php_strip_whitespace($path); if (!$contents) { if (!file_exists($path)) { From bb08f76ad99142e4253b7ac90294fe1dbc266579 Mon Sep 17 00:00:00 2001 From: Niels Keurentjes Date: Sat, 6 Feb 2016 02:32:08 +0100 Subject: [PATCH 3/5] Use error_get_last to verify why php_strip_whitespace would return an empty string. --- src/Composer/Autoload/ClassMapGenerator.php | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index 3ad26f7f2..9bacee580 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -122,20 +122,20 @@ class ClassMapGenerator $extraTypes .= '|enum'; } - try { - // Use @ here instead of Silencer to actively suppress 'unhelpful' output - // @link https://github.com/composer/composer/pull/4886 - $contents = @php_strip_whitespace($path); - if (!$contents) { - if (!file_exists($path)) { - throw new \RuntimeException(sprintf('File at "%s" does not exist, check your classmap definitions', $path)); - } elseif (!is_readable($path)) { - throw new \RuntimeException(sprintf('File at "%s" is not readable, check its permissions', $path)); - } - throw new \RuntimeException(sprintf('File at "%s" could not be parsed as PHP - it may be binary or corrupted', $path)); + // Use @ here instead of Silencer to actively suppress 'unhelpful' output + // @link https://github.com/composer/composer/pull/4886 + error_clear_last(); + $contents = @php_strip_whitespace($path); + if (!$contents) { + if (is_null(error_get_last())) { + // No error, so the input file was really empty or contained only comments + return array(); + } elseif (!file_exists($path)) { + throw new \RuntimeException(sprintf('File at "%s" does not exist, check your classmap definitions', $path)); + } elseif (!is_readable($path)) { + throw new \RuntimeException(sprintf('File at "%s" is not readable, check its permissions', $path)); } - } catch (\Exception $e) { - throw new \RuntimeException('Could not scan for classes inside '.$path.": \n".$e->getMessage(), 0, $e); + throw new \RuntimeException(sprintf('File at "%s" could not be parsed as PHP - it may be binary or corrupted', $path)); } // return early if there is no chance of matching anything in this file From 6a53b1df42e124a95d12a5e6c953fa28ae0c8235 Mon Sep 17 00:00:00 2001 From: Niels Keurentjes Date: Sat, 6 Feb 2016 02:40:16 +0100 Subject: [PATCH 4/5] Further reorganized messy checking code. --- src/Composer/Autoload/ClassMapGenerator.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index 9bacee580..818367c98 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -127,15 +127,21 @@ class ClassMapGenerator error_clear_last(); $contents = @php_strip_whitespace($path); if (!$contents) { - if (is_null(error_get_last())) { - // No error, so the input file was really empty or contained only comments + $error = error_get_last(); + if (is_null($error)) { + // No error, so the input file was really empty and thus contains no classes return array(); } elseif (!file_exists($path)) { - throw new \RuntimeException(sprintf('File at "%s" does not exist, check your classmap definitions', $path)); + $message = 'File at "%s" does not exist, check your classmap definitions'; } elseif (!is_readable($path)) { - throw new \RuntimeException(sprintf('File at "%s" is not readable, check its permissions', $path)); + $message = 'File at "%s" is not readable, check its permissions'; + } else { + $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted'; } - throw new \RuntimeException(sprintf('File at "%s" could not be parsed as PHP - it may be binary or corrupted', $path)); + if (isset($error['message'])) { + $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message']; + } + throw new \RuntimeException(sprintf($message, $path)); } // return early if there is no chance of matching anything in this file From 0b55a0ca9122abfd7ede51d67f5defe4dfd64daf Mon Sep 17 00:00:00 2001 From: Niels Keurentjes Date: Sat, 6 Feb 2016 02:58:36 +0100 Subject: [PATCH 5/5] Can't use error_clear_last as it was introduced in PHP7. --- src/Composer/Autoload/ClassMapGenerator.php | 11 +++++------ .../Composer/Test/Autoload/ClassMapGeneratorTest.php | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index 818367c98..59542a4a7 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -124,20 +124,19 @@ class ClassMapGenerator // Use @ here instead of Silencer to actively suppress 'unhelpful' output // @link https://github.com/composer/composer/pull/4886 - error_clear_last(); $contents = @php_strip_whitespace($path); if (!$contents) { - $error = error_get_last(); - if (is_null($error)) { - // No error, so the input file was really empty and thus contains no classes - return array(); - } elseif (!file_exists($path)) { + if (!file_exists($path)) { $message = 'File at "%s" does not exist, check your classmap definitions'; } elseif (!is_readable($path)) { $message = 'File at "%s" is not readable, check its permissions'; + } elseif ('' === trim(file_get_contents($path))) { + // The input file was really empty and thus contains no classes + return array(); } else { $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted'; } + $error = error_get_last(); if (isset($error['message'])) { $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message']; } diff --git a/tests/Composer/Test/Autoload/ClassMapGeneratorTest.php b/tests/Composer/Test/Autoload/ClassMapGeneratorTest.php index cd3d43260..13cf7cd83 100644 --- a/tests/Composer/Test/Autoload/ClassMapGeneratorTest.php +++ b/tests/Composer/Test/Autoload/ClassMapGeneratorTest.php @@ -113,7 +113,7 @@ class ClassMapGeneratorTest extends TestCase /** * @expectedException \RuntimeException - * @expectedExceptionMessage Could not scan for classes inside + * @expectedExceptionMessage does not exist */ public function testFindClassesThrowsWhenFileDoesNotExist() {