mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix memory leak in shm_get_var() when variable is corrupted
This path wasn't tested (clearly). To trigger this we use FFI, which seemed like the easiest way that doesn't involve using another process messing with the shared memory. Closes GH-21388.
This commit is contained in:
3
NEWS
3
NEWS
@@ -23,6 +23,9 @@ PHP NEWS
|
|||||||
. Fixed bug GH-20627 (Cannot identify some avif images with getimagesize).
|
. Fixed bug GH-20627 (Cannot identify some avif images with getimagesize).
|
||||||
(y-guyon)
|
(y-guyon)
|
||||||
|
|
||||||
|
- Sysvshm:
|
||||||
|
. Fix memory leak in shm_get_var() when variable is corrupted. (ndossche)
|
||||||
|
|
||||||
12 Mar 2026, PHP 8.4.19
|
12 Mar 2026, PHP 8.4.19
|
||||||
|
|
||||||
- Core:
|
- Core:
|
||||||
|
|||||||
@@ -309,11 +309,13 @@ PHP_FUNCTION(shm_get_var)
|
|||||||
shm_data = &shm_var->mem;
|
shm_data = &shm_var->mem;
|
||||||
|
|
||||||
PHP_VAR_UNSERIALIZE_INIT(var_hash);
|
PHP_VAR_UNSERIALIZE_INIT(var_hash);
|
||||||
if (php_var_unserialize(return_value, (const unsigned char **) &shm_data, (unsigned char *) shm_data + shm_var->length, &var_hash) != 1) {
|
int res = php_var_unserialize(return_value, (const unsigned char **) &shm_data, (unsigned char *) shm_data + shm_var->length, &var_hash);
|
||||||
php_error_docref(NULL, E_WARNING, "Variable data in shared memory is corrupted");
|
|
||||||
RETVAL_FALSE;
|
|
||||||
}
|
|
||||||
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||||
|
if (res != 1) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Variable data in shared memory is corrupted");
|
||||||
|
zval_ptr_dtor(return_value);
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|||||||
37
ext/sysvshm/tests/shm_get_var_leak.phpt
Normal file
37
ext/sysvshm/tests/shm_get_var_leak.phpt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
--TEST--
|
||||||
|
shm_get_var() leaks if variable is corrupted
|
||||||
|
--EXTENSIONS--
|
||||||
|
sysvshm
|
||||||
|
ffi
|
||||||
|
--INI--
|
||||||
|
ffi.enable=1
|
||||||
|
--SKIPIF--
|
||||||
|
<?php
|
||||||
|
if (!function_exists('ftok')) die('skip needs ftok');
|
||||||
|
if (PHP_INT_SIZE !== 8) die('skip only for 64-bit');
|
||||||
|
if (PHP_OS_FAMILY !== 'Linux') die('skip only for decent operating systems');
|
||||||
|
?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$key = ftok(__FILE__, 't');
|
||||||
|
$s = shm_attach($key, 128);
|
||||||
|
|
||||||
|
shm_put_var($s, 0, [1, 2]);
|
||||||
|
|
||||||
|
$ffi = FFI::cdef(<<<CODE
|
||||||
|
int shmget(int, size_t, int);
|
||||||
|
char *shmat(int, const void *, int);
|
||||||
|
CODE);
|
||||||
|
$ptr = $ffi->shmat($ffi->shmget($key, 0, 0), $ffi->new('void *'), 0);
|
||||||
|
|
||||||
|
$ptr[0x40 + 13] = 0; // Corrupt first byte of second element of serialized data
|
||||||
|
|
||||||
|
var_dump(shm_get_var($s, 0));
|
||||||
|
|
||||||
|
shm_remove($s);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: shm_get_var(): Variable data in shared memory is corrupted in %s on line %d
|
||||||
|
bool(false)
|
||||||
Reference in New Issue
Block a user