diff --git a/.docker/php/8.1/Dockerfile b/.docker/php/8.1/Dockerfile
index e4586be..9951001 100644
--- a/.docker/php/8.1/Dockerfile
+++ b/.docker/php/8.1/Dockerfile
@@ -1,4 +1,4 @@
-FROM php:8.1.0RC2-fpm-alpine
+FROM php:8.1-fpm-alpine
ENV PHP_CONF_DIR=/usr/local/etc/php-fpm.d
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ec06aa9..df9ef5c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -69,7 +69,7 @@ jobs:
uses: mheap/phpunit-matcher-action@v1
- name: Run unit tests on PHP ${{ matrix.php }}
- run: make -s "test-php-${{ matrix.php }}"
+ run: make -s -e "PHPUNIT_OPTIONS=--teamcity" "test-php-${{ matrix.php }}"
env:
COMPOSE_INTERACTIVE_NO_CLI: 1
PHPUNIT_OPTIONS: "--teamcity"
diff --git a/.phive/phars.xml b/.phive/phars.xml
index 02d10c5..8a0ee75 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -1,8 +1,8 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77a220f..79a7456 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file. This project adheres
to [Semantic Versioning](http://semver.org/) and [Keep a CHANGELOG](http://keepachangelog.com).
+## [3.1.7] - 2021-12-07
+
+* Make sure length values are within valid bounds
+
## [3.1.6] - 2021-09-23
### Added
@@ -410,6 +414,8 @@ on [Pierrick Charron](https://github.com/adoy)'s [PHP-FastCGI-Client](https://gi
socket connection)
* Method `Client->getValues()`
+[3.1.7]: https://github.com/hollodotme/fast-cgi-client/compare/v3.1.6...v3.1.7
+
[3.1.6]: https://github.com/hollodotme/fast-cgi-client/compare/v3.1.5...v3.1.6
[3.1.5]: https://github.com/hollodotme/fast-cgi-client/compare/v3.1.4...v3.1.5
diff --git a/Makefile b/Makefile
index 59fcdb9..cbcba88 100644
--- a/Makefile
+++ b/Makefile
@@ -80,7 +80,7 @@ composer-update:
.PHONY: composer-update
## Run all tests on all PHP versions
-tests: composer-validate phplint test-php-7.1 test-php-7.2 test-php-7.3 test-php-7.4 test-php-8.0 test-php-8.1 phpstan
+tests: composer-validate phplint test-php-7.1 test-php-7.2 test-php-7.3 test-php-7.4 test-php-8.0 test-php-8.1 dcdown phpstan
.PHONY: tests
INTEGRATION_WORKER_DIR = ./tests/Integration/Workers
@@ -91,6 +91,7 @@ make-integration-workers-accessible:
.PHONY: make-integration-workers-accessible
PHP_OPTIONS = -d error_reporting=-1 -dmemory_limit=-1 -d xdebug.mode=coverage -d auto_prepend_file=tests/xdebug-filter.php
+PHPUNIT_OPTIONS = --testdox
## Run PHP linting
phplint:
diff --git a/phpstan.neon b/phpstan.neon
index cb2d4fb..27024df 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -2,6 +2,6 @@ parameters:
paths:
- src
- tests
- level: max
+ level: 8
bootstrapFiles:
- /repo/.tools/phpunit-7.phar
\ No newline at end of file
diff --git a/src/Encoders/NameValuePairEncoder.php b/src/Encoders/NameValuePairEncoder.php
index fcc3fe2..eae6276 100644
--- a/src/Encoders/NameValuePairEncoder.php
+++ b/src/Encoders/NameValuePairEncoder.php
@@ -1,4 +1,4 @@
- $pairs
+ * @param array $pairs
*
* @return string
*/
@@ -105,25 +105,25 @@ public function decodePairs( string $data, int $length = -1 ) : array
while ( $p !== $length )
{
- $nameLength = ord( $data[$p++] );
+ $nameLength = ord( $data[ $p++ ] );
if ( $nameLength >= 128 )
{
$nameLength &= (0x7F << 24);
- $nameLength |= (ord( $data[$p++] ) << 16);
- $nameLength |= (ord( $data[$p++] ) << 8);
- $nameLength |= ord( $data[$p++] );
+ $nameLength |= (ord( $data[ $p++ ] ) << 16);
+ $nameLength |= (ord( $data[ $p++ ] ) << 8);
+ $nameLength |= ord( $data[ $p++ ] );
}
- $valueLength = ord( $data[$p++] );
+ $valueLength = ord( $data[ $p++ ] );
if ( $valueLength >= 128 )
{
$valueLength = ($nameLength & 0x7F << 24);
- $valueLength |= (ord( $data[$p++] ) << 16);
- $valueLength |= (ord( $data[$p++] ) << 8);
- $valueLength |= ord( $data[$p++] );
+ $valueLength |= (ord( $data[ $p++ ] ) << 16);
+ $valueLength |= (ord( $data[ $p++ ] ) << 8);
+ $valueLength |= ord( $data[ $p++ ] );
}
$array[ substr( $data, $p, $nameLength ) ] = substr( $data, $p + $nameLength, $valueLength );
- $p += ($nameLength + $valueLength);
+ $p += ($nameLength + $valueLength);
}
return $array;
diff --git a/src/Interfaces/EncodesNameValuePair.php b/src/Interfaces/EncodesNameValuePair.php
index cf0492b..5471d29 100644
--- a/src/Interfaces/EncodesNameValuePair.php
+++ b/src/Interfaces/EncodesNameValuePair.php
@@ -30,7 +30,7 @@
interface EncodesNameValuePair
{
/**
- * @param array $pairs
+ * @param array $pairs
*
* @return string
*/
diff --git a/src/RequestContents/JsonData.php b/src/RequestContents/JsonData.php
index 7870306..929afa5 100644
--- a/src/RequestContents/JsonData.php
+++ b/src/RequestContents/JsonData.php
@@ -5,6 +5,7 @@
use hollodotme\FastCGI\Interfaces\ComposesRequestContent;
use RuntimeException;
use function json_encode;
+use const PHP_INT_MAX;
final class JsonData implements ComposesRequestContent
{
@@ -14,19 +15,19 @@ final class JsonData implements ComposesRequestContent
/** @var int */
private $encodingOptions;
- /** @var int */
+ /** @var int<1, max> */
private $encodingDepth;
/**
* @param mixed $data
* @param int $options
- * @param int $depth
+ * @param int<1, max> $depth
*/
public function __construct( $data, int $options = 0, int $depth = 512 )
{
$this->data = $data;
$this->encodingOptions = $options;
- $this->encodingDepth = $depth;
+ $this->encodingDepth = max( 1, min( $depth, PHP_INT_MAX ) );
}
public function getContentType() : string
diff --git a/src/Sockets/Socket.php b/src/Sockets/Socket.php
index 361f1f7..979b6d5 100644
--- a/src/Sockets/Socket.php
+++ b/src/Sockets/Socket.php
@@ -44,7 +44,9 @@
use function fread;
use function fwrite;
use function is_resource;
+use function max;
use function microtime;
+use function min;
use function ord;
use function str_repeat;
use function stream_get_meta_data;
@@ -54,14 +56,13 @@
use function stream_socket_shutdown;
use function strlen;
use function substr;
+use const PHP_INT_MAX;
use const STREAM_SHUT_RDWR;
final class Socket
{
private const BEGIN_REQUEST = 1;
- private const ABORT_REQUEST = 2;
-
private const END_REQUEST = 3;
private const PARAMS = 4;
@@ -314,11 +315,11 @@ private function handleFailedResource( ?int $errorNumber, ?string $errorString )
if ( null !== $lastError )
{
$lastErrorException = new ErrorException(
- $lastError['message'] ?? '[No message available]',
+ $lastError['message'],
0,
- $lastError['type'] ?? E_ERROR,
- $lastError['file'] ?? '[No file available]',
- $lastError['line'] ?? '[No line available]'
+ $lastError['type'],
+ $lastError['file'],
+ $lastError['line']
);
}
@@ -502,11 +503,11 @@ private function readPacket() : ?array
if ( $packet['contentLength'] )
{
- $length = $packet['contentLength'];
+ $length = $this->getValidLength( (int)$packet['contentLength'] );
while ( $length && ($buffer = fread( $this->resource, $length )) !== false )
{
- $length -= strlen( (string)$buffer );
+ $length = $this->getValidLength( $length - strlen( (string)$buffer ) );
$packet['content'] .= $buffer;
}
}
@@ -514,7 +515,7 @@ private function readPacket() : ?array
if ( $packet['paddingLength'] )
{
/** @noinspection UnusedFunctionResultInspection */
- fread( $this->resource, (int)$packet['paddingLength'] );
+ fread( $this->resource, $this->getValidLength( (int)$packet['paddingLength'] ) );
}
return $packet;
@@ -523,6 +524,16 @@ private function readPacket() : ?array
return null;
}
+ /**
+ * @param int $value
+ *
+ * @return int<0, max>
+ */
+ private function getValidLength( int $value ) : int
+ {
+ return (int)max( 0, min( $value, PHP_INT_MAX ) );
+ }
+
private function notifyPassThroughCallbacks( string $outputBuffer, string $errorBuffer ) : void
{
foreach ( $this->passThroughCallbacks as $passThroughCallback )