diff --git a/ext/sysvshm/sysvshm.c b/ext/sysvshm/sysvshm.c index 84c10add85ef..9c68c09147d4 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-- + +--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-- + 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-- + +--EXPECTF-- +Warning: shm_attach(): Failed for key 0x%x: segment too small in %s on line %d +bool(false) +--CLEAN-- +