[PHP-CVS] [php-src] PHP-8.5: Merge branch 'PHP-8.4' into PHP-8.5

[email protected] (David Carlier) Sun, 2 Aug 2026 20:56:22 +0000
Newsgroups php.cvs
Message-ID <[email protected]>
Author: David Carlier (devnexen)
Date: 2026-08-02T21:54:51+01:00

Commit: https://github.com/php/php-src/commit/947f4d2b662f1279ec502b8d9e4ee4b700858285
Raw diff: https://github.com/php/php-src/commit/947f4d2b662f1279ec502b8d9e4ee4b700858285.diff

Merge branch 'PHP-8.4' into PHP-8.5

* PHP-8.4:
  ext/sysvshm: do not trust $size when opening an existing segment

Changed paths:
  A  ext/sysvshm/tests/shm_attach_existing_segment_size.phpt
  A  ext/sysvshm/tests/shm_attach_existing_segment_too_small.phpt
  M  ext/sysvshm/sysvshm.c


Diff:

diff --git a/ext/sysvshm/sysvshm.c b/ext/sysvshm/sysvshm.c
index 179fe0ed139c..f7b5b0dcdae2 100644
--- a/ext/sysvshm/sysvshm.c
+++ b/ext/sysvshm/sysvshm.c
@@ -130,6 +130,7 @@ PHP_FUNCTION(shm_attach)
 	sysvshm_shm *shm_list_ptr;
 	char *shm_ptr;
 	sysvshm_chunk_head *chunk_ptr;
+	struct shmid_ds shm_desc;
 	zend_long shm_key, shm_id, shm_size, shm_flag = 0666;
 	bool shm_size_is_null = 1;
 	bool created = false;
@@ -168,6 +169,25 @@ PHP_FUNCTION(shm_attach)
 		RETURN_FALSE;
 	}
 
+	if (shmctl(shm_id, IPC_STAT, &shm_desc) < 0) {
+		php_error_docref(NULL, E_WARNING, "Failed for key 0x" ZEND_XLONG_FMT ": %s", shm_key, strerror(errno));
+		shmdt(shm_ptr);
+		if (created) {
+			shmctl(shm_id, IPC_RMID, NULL);
+		}
+		RETURN_FALSE;
+	}
+	shm_size = (zend_long)shm_desc.shm_segsz;
+
+	if (shm_size < (zend_long) sizeof(sysvshm_chunk_head)) {
+		php_error_docref(NULL, E_WARNING, "Failed for key 0x" ZEND_XLONG_FMT ": segment too small", shm_key);
+		shmdt(shm_ptr);
+		if (created) {
+			shmctl(shm_id, IPC_RMID, NULL);
+		}
+		RETURN_FALSE;
+	}
+
 	/* check if shm is already initialized */
 	chunk_ptr = (sysvshm_chunk_head *) shm_ptr;
 	if (strcmp((char*) &(chunk_ptr->magic), "PHP_SM") != 0) {
diff --git a/ext/sysvshm/tests/shm_attach_existing_segment_size.phpt b/ext/sysvshm/tests/shm_attach_existing_segment_size.phpt
new file mode 100644
index 000000000000..8f7f233e0d5f
--- /dev/null
+++ b/ext/sysvshm/tests/shm_attach_existing_segment_size.phpt
@@ -0,0 +1,36 @@
+--TEST--
+shm_attach() takes the size of an existing segment from the kernel, not from $size
+--EXTENSIONS--
+sysvshm
+shmop
+--FILE--
+<?php
+$key = 0x53484D31;
+
+$raw = shmop_open($key, 'n', 0600, 4096);
+
+$shm = shm_attach($key, 10 * 1024 * 1024);
+var_dump($shm instanceof SysvSharedMemory);
+
+var_dump(shm_put_var($shm, 1, str_repeat('A', 1024 * 1024)));
+
+var_dump(shm_put_var($shm, 2, 'ok'));
+var_dump(shm_get_var($shm, 2));
+
+var_dump(shm_remove($shm));
+?>
+--EXPECTF--
+bool(true)
+
+Warning: shm_put_var(): Not enough shared memory left in %s on line %d
+bool(false)
+bool(true)
+string(2) "ok"
+bool(true)
+--CLEAN--
+<?php
+$raw = @shmop_open(0x53484D31, 'w', 0, 0);
+if ($raw) {
+    shmop_delete($raw);
+}
+?>
diff --git a/ext/sysvshm/tests/shm_attach_existing_segment_too_small.phpt b/ext/sysvshm/tests/shm_attach_existing_segment_too_small.phpt
new file mode 100644
index 000000000000..eec56c8f0919
--- /dev/null
+++ b/ext/sysvshm/tests/shm_attach_existing_segment_too_small.phpt
@@ -0,0 +1,25 @@
+--TEST--
+shm_attach() rejects an existing segment too small to hold its header
+--EXTENSIONS--
+sysvshm
+shmop
+--FILE--
+<?php
+$key = 0x53484D32;
+
+$raw = shmop_open($key, 'n', 0600, 8);
+
+var_dump(shm_attach($key, 1024));
+
+shmop_delete($raw);
+?>
+--EXPECTF--
+Warning: shm_attach(): Failed for key 0x%x: segment too small in %s on line %d
+bool(false)
+--CLEAN--
+<?php
+$raw = @shmop_open(0x53484D32, 'w', 0, 0);
+if ($raw) {
+    shmop_delete($raw);
+}
+?>