From 0c9b5a86a2f52ed61d6db838fb1609c877a47a40 Mon Sep 17 00:00:00 2001 From: Paragon Initiative Enterprises Date: Fri, 3 Feb 2017 13:31:53 -0500 Subject: [PATCH 1/3] Psalm integration. --- .travis.yml | 36 ++++++++++++++++++++------------ CHANGELOG.md | 5 +++++ lib/byte_safe_strings.php | 14 ++++++------- lib/cast_to_int.php | 8 ++++--- lib/random.php | 4 ++++ lib/random_bytes_dev_urandom.php | 35 +++++++++++++++++++++++-------- lib/random_int.php | 5 ----- 7 files changed, 70 insertions(+), 37 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7b81560..213d49c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,22 +1,32 @@ language: php - -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - hhvm +sudo: false matrix: fast_finish: true + include: + - php: "5.3" + env: USE_PSALM=0 + - php: "5.4" + env: USE_PSALM=0 + - php: "5.5" + env: USE_PSALM=0 + - php: "5.6" + env: USE_PSALM=1 + - php: "7.0" + env: USE_PSALM=1 + - php: "7.1" + env: USE_PSALM=1 + - php: "hhvm" + env: USE_PSALM=1 allow_failures: - - php: hhvm - -sudo: false + - php: "hhvm" install: - - composer install + - composer self-update + - composer install + - if [[ $USE_PSALM -eq 1 ]]; then composer require --dev "vimeo/psalm:dev-master"; fi script: - - ./phpunit.sh + - vendor/bin/phpunit + - php -dmbstring.func_overload=7 vendor/bin/phpunit + - if [[ $USE_PSALM -eq 1 ]]; then vendor/bin/psalm; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 077760c..1979e78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +### Version 2.0.5 - 2017-??-?? + +* Run random_compat through the static analysis tool, [psalm](https://github.com/vimeo/psalm), + as part of our continuous integration process. + ### Version 2.0.4 - 2016-11-07 * Don't unnecessarily prevent `mcrypt_create_iv()` from being used. diff --git a/lib/byte_safe_strings.php b/lib/byte_safe_strings.php index dd03690..6de294f 100644 --- a/lib/byte_safe_strings.php +++ b/lib/byte_safe_strings.php @@ -51,7 +51,7 @@ function RandomCompat_strlen($binary_string) ); } - return mb_strlen($binary_string, '8bit'); + return (int) mb_strlen($binary_string, '8bit'); } } else { @@ -73,7 +73,7 @@ function RandomCompat_strlen($binary_string) 'RandomCompat_strlen() expects a string' ); } - return strlen($binary_string); + return (int) strlen($binary_string); } } } @@ -118,7 +118,7 @@ function RandomCompat_substr($binary_string, $start, $length = null) * mb_substr($str, 0, NULL, '8bit') returns an empty string on * PHP 5.3, so we have to find the length ourselves. */ - $length = RandomCompat_strlen($length) - $start; + $length = RandomCompat_strlen($binary_string) - $start; } elseif (!is_int($length)) { throw new TypeError( 'RandomCompat_substr(): Third argument should be an integer, or omitted' @@ -130,10 +130,10 @@ function RandomCompat_substr($binary_string, $start, $length = null) return ''; } if ($start > RandomCompat_strlen($binary_string)) { - return false; + return ''; } - return mb_substr($binary_string, $start, $length, '8bit'); + return (string) mb_substr($binary_string, $start, $length, '8bit'); } } else { @@ -172,10 +172,10 @@ function RandomCompat_substr($binary_string, $start, $length = null) ); } - return substr($binary_string, $start, $length); + return (string) substr($binary_string, $start, $length); } - return substr($binary_string, $start); + return (string) substr($binary_string, $start); } } } diff --git a/lib/cast_to_int.php b/lib/cast_to_int.php index 65e9d21..57a6935 100644 --- a/lib/cast_to_int.php +++ b/lib/cast_to_int.php @@ -40,7 +40,7 @@ * @param int|float $number The number we want to convert to an int * @param boolean $fail_open Set to true to not throw an exception * - * @return int (or float if $fail_open) + * @return int|float * * @throws TypeError */ @@ -60,8 +60,10 @@ function RandomCompat_intval($number, $fail_open = false) $number = (int) $number; } - if (is_int($number) || $fail_open) { - return $number; + if (is_int($number)) { + return (int) $number; + } elseif ($fail_open) { + return (float) $number; } throw new TypeError( diff --git a/lib/random.php b/lib/random.php index aa3fe96..eb08f01 100644 --- a/lib/random.php +++ b/lib/random.php @@ -199,6 +199,10 @@ class_exists('COM') /** * We don't have any more options, so let's throw an exception right now * and hope the developer won't let it fail silently. + * + * @param mixed $length + * @return void + * @throws Exception */ function random_bytes($length) { diff --git a/lib/random_bytes_dev_urandom.php b/lib/random_bytes_dev_urandom.php index aaccd5a..05a9693 100644 --- a/lib/random_bytes_dev_urandom.php +++ b/lib/random_bytes_dev_urandom.php @@ -104,33 +104,50 @@ function random_bytes($bytes) * page load. */ if (!empty($fp)) { + /** + * @var int + */ $remaining = $bytes; + + /** + * @var string|bool + */ $buf = ''; /** * We use fread() in a loop to protect against partial reads */ do { + /** + * @var string|bool + */ $read = fread($fp, $remaining); - if ($read === false) { - /** - * We cannot safely read from the file. Exit the - * do-while loop and trigger the exception condition - */ - $buf = false; - break; + if (!is_string($read)) { + if ($read === false) { + /** + * We cannot safely read from the file. Exit the + * do-while loop and trigger the exception condition + * + * @var string|bool + */ + $buf = false; + break; + } } /** * Decrease the number of bytes returned from remaining */ $remaining -= RandomCompat_strlen($read); - $buf .= $read; + /** + * @var string|bool + */ + $buf = $buf . $read; } while ($remaining > 0); /** * Is our result valid? */ - if ($buf !== false) { + if (is_string($buf)) { if (RandomCompat_strlen($buf) === $bytes) { /** * Return our random entropy buffer here: diff --git a/lib/random_int.php b/lib/random_int.php index ce0ccbd..565fc15 100644 --- a/lib/random_int.php +++ b/lib/random_int.php @@ -151,11 +151,6 @@ function random_int($min, $max) * Let's grab the necessary number of random bytes */ $randomByteString = random_bytes($bytes); - if ($randomByteString === false) { - throw new Exception( - 'Random number generator failure' - ); - } /** * Let's turn $randomByteString into an integer From cfa429ff73cafc5da934178246f6ed9f8b014de0 Mon Sep 17 00:00:00 2001 From: Paragon Initiative Enterprises Date: Fri, 3 Feb 2017 14:04:12 -0500 Subject: [PATCH 2/3] Add libsodium stub for randombytes --- other/ide_stubs/libsodium.php | 46 +++++++++++++++++++++++++++++++++++ psalm-autoload.php | 1 + 2 files changed, 47 insertions(+) create mode 100644 other/ide_stubs/libsodium.php diff --git a/other/ide_stubs/libsodium.php b/other/ide_stubs/libsodium.php new file mode 100644 index 0000000..2c80570 --- /dev/null +++ b/other/ide_stubs/libsodium.php @@ -0,0 +1,46 @@ + Date: Fri, 3 Feb 2017 14:14:48 -0500 Subject: [PATCH 3/3] Fix stubs. Remove UndefinedClass suppression. --- lib/random_bytes_com_dotnet.php | 5 ++ lib/random_bytes_libsodium_legacy.php | 2 +- other/ide_stubs/COM.php | 8 +- other/ide_stubs/README.md | 2 + other/ide_stubs/com_exception.php | 2 - other/ide_stubs/libsodium.php | 112 ++++++++++++++++++-------- psalm.xml | 1 - 7 files changed, 87 insertions(+), 45 deletions(-) diff --git a/lib/random_bytes_com_dotnet.php b/lib/random_bytes_com_dotnet.php index f068b6c..97df3f3 100644 --- a/lib/random_bytes_com_dotnet.php +++ b/lib/random_bytes_com_dotnet.php @@ -55,6 +55,11 @@ function random_bytes($bytes) } $buf = ''; + if (!class_exists('COM')) { + throw new Error( + 'COM does not exist' + ); + } $util = new COM('CAPICOM.Utilities.1'); $execCount = 0; diff --git a/lib/random_bytes_libsodium_legacy.php b/lib/random_bytes_libsodium_legacy.php index f8d6a7f..7bc9789 100644 --- a/lib/random_bytes_libsodium_legacy.php +++ b/lib/random_bytes_libsodium_legacy.php @@ -72,7 +72,7 @@ function random_bytes($bytes) $buf = Sodium::randombytes_buf($bytes); } - if ($buf !== false) { + if (is_string($buf)) { if (RandomCompat_strlen($buf) === $bytes) { return $buf; } diff --git a/other/ide_stubs/COM.php b/other/ide_stubs/COM.php index 22983f3..4ba4bb3 100644 --- a/other/ide_stubs/COM.php +++ b/other/ide_stubs/COM.php @@ -15,12 +15,6 @@ class COM */ public function GetRandom($bytes, $dummy) { - static $fp = null; - if (!$fp) { - $fp = fopen('/dev/urandom', 'rb'); - } - return fread($fp, $bytes); + return ''; } } - -throw new Exception('Attempting to include IDE stub files in a project.'); diff --git a/other/ide_stubs/README.md b/other/ide_stubs/README.md index 5fa290e..532711b 100644 --- a/other/ide_stubs/README.md +++ b/other/ide_stubs/README.md @@ -2,4 +2,6 @@ These exist to reduce false positive errors on PHPStorm and other IDEs. +They also exist so Psalm has some idea what's going on. + Don't use them in your project. diff --git a/other/ide_stubs/com_exception.php b/other/ide_stubs/com_exception.php index 49ed936..8f62c27 100644 --- a/other/ide_stubs/com_exception.php +++ b/other/ide_stubs/com_exception.php @@ -9,5 +9,3 @@ class com_exception extends Exception { } - -throw new Exception('Attempting to include IDE stub files in a project.'); diff --git a/other/ide_stubs/libsodium.php b/other/ide_stubs/libsodium.php index 2c80570..3381bd3 100644 --- a/other/ide_stubs/libsodium.php +++ b/other/ide_stubs/libsodium.php @@ -1,46 +1,90 @@ -