From bdb378df19856d461de73af69da10a3d6639756c Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 4 Oct 2024 23:00:45 +0100 Subject: [PATCH] Fix GH-15395: php-fpm: zend_mm_heap corrupted with cgi-fcgi request Co-authored-by: David Carlier Closes GH-16227 --- main/SAPI.c | 3 + main/main.c | 4 +- sapi/fpm/tests/gh15395-php-auth-shutdown.phpt | 61 +++++++++++++++++++ sapi/fpm/tests/tester.inc | 3 +- 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 sapi/fpm/tests/gh15395-php-auth-shutdown.phpt diff --git a/main/SAPI.c b/main/SAPI.c index 09b028e55166e..d0226ded65bec 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -507,12 +507,15 @@ SAPI_API void sapi_deactivate_module(void) } if (SG(request_info).auth_user) { efree(SG(request_info).auth_user); + SG(request_info).auth_user = NULL; } if (SG(request_info).auth_password) { efree(SG(request_info).auth_password); + SG(request_info).auth_password = NULL; } if (SG(request_info).auth_digest) { efree(SG(request_info).auth_digest); + SG(request_info).auth_digest = NULL; } if (SG(request_info).content_type_dup) { efree(SG(request_info).content_type_dup); diff --git a/main/main.c b/main/main.c index 0adecd10ffcca..3e03951e87755 100644 --- a/main/main.c +++ b/main/main.c @@ -2672,7 +2672,9 @@ PHPAPI int php_handle_auth_data(const char *auth) if (pass) { *pass++ = '\0'; SG(request_info).auth_user = estrndup(ZSTR_VAL(user), ZSTR_LEN(user)); - SG(request_info).auth_password = estrdup(pass); + if (strlen(pass) > 0) { + SG(request_info).auth_password = estrdup(pass); + } ret = 0; } zend_string_free(user); diff --git a/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt b/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt new file mode 100644 index 0000000000000..b9875dd10ef5e --- /dev/null +++ b/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt @@ -0,0 +1,61 @@ +--TEST-- +FPM: GH-15335 - PHP_AUTH shutdown use after free +--SKIPIF-- + +--FILE-- +createSourceFileAndScriptName(); +$tester->start(); +$tester->expectLogStartNotices(); +$tester + ->request( + headers: [ "HTTP_AUTHORIZATION" => "Basic Zm9vOg==", "REQUEST_METHOD" => "GET"], + uri: $scriptName, + address: '{{ADDR}}', + scriptFilename: __DIR__ . "/__unknown.php", + scriptName: "/", + ) + ->expectStatus('404 Not Found'); +$tester + ->request( + uri: $scriptName, + address: '{{ADDR}}', + params: [], + ); +$tester->expectNoLogPattern("/zend_mm_heap corrupted/"); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index ed0988f883ac1..bf4f3d918131c 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -762,6 +762,7 @@ class Tester string|array $stdin = null, bool $expectError = false, int $readLimit = -1, + array $params = null, ): Response { if ($this->hasError()) { return $this->createResponse(expectInvalid: true); @@ -771,7 +772,7 @@ class Tester $stdin = $this->parseStdin($stdin, $headers); } - $params = $this->getRequestParams($query, $headers, $uri, $scriptFilename, $scriptName, $stdin); + $params = $params ?? $this->getRequestParams($query, $headers, $uri, $scriptFilename, $scriptName, $stdin); $this->trace('Request params', $params); try {