Commit ea8aab92208 for php.net
commit ea8aab92208186799112d1aa53dde56685332f37
Author: ndossche <7771979+ndossche@users.noreply.github.com>
Date: Sun Mar 8 23:00:49 2026 +0100
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.
diff --git a/NEWS b/NEWS
index 5380688ce3d..542447107fa 100644
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,9 @@ PHP NEWS
. Fixed bug GH-20627 (Cannot identify some avif images with getimagesize).
(y-guyon)
+- Sysvshm:
+ . Fix memory leak in shm_get_var() when variable is corrupted. (ndossche)
+
12 Mar 2026, PHP 8.4.19
- Core:
diff --git a/ext/sysvshm/sysvshm.c b/ext/sysvshm/sysvshm.c
index 332a8b47af1..3fa7c77add3 100644
--- a/ext/sysvshm/sysvshm.c
+++ b/ext/sysvshm/sysvshm.c
@@ -309,11 +309,13 @@ PHP_FUNCTION(shm_get_var)
shm_data = &shm_var->mem;
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_VAR_UNSERIALIZE_DESTROY(var_hash);
+ if (res != 1) {
php_error_docref(NULL, E_WARNING, "Variable data in shared memory is corrupted");
- RETVAL_FALSE;
+ zval_ptr_dtor(return_value);
+ RETURN_FALSE;
}
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
}
/* }}} */
diff --git a/ext/sysvshm/tests/shm_get_var_leak.phpt b/ext/sysvshm/tests/shm_get_var_leak.phpt
new file mode 100644
index 00000000000..037bad7c41d
--- /dev/null
+++ b/ext/sysvshm/tests/shm_get_var_leak.phpt
@@ -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)