Skip to content

Commit 8db6bd5

Browse files
committed
Fix the replacement for shmget in Windows
Closes #9944 https://man7.org/linux/man-pages/man2/shmget.2.html notes The name choice IPC_PRIVATE was perhaps unfortunate, IPC_NEW would more clearly show its function.
1 parent 1562ba5 commit 8db6bd5

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

TSRM/tsrm_win32.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,9 @@ TSRM_API int shmget(key_t key, size_t size, int flags)
626626

627627
shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
628628
info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
629+
} else {
630+
/* IPC_PRIVATE always creates a new segment even if IPC_CREAT flag isn't passed. */
631+
flags |= IPC_CREAT;
629632
}
630633

631634
if (!shm_handle && !info_handle) {
@@ -662,6 +665,19 @@ TSRM_API int shmget(key_t key, size_t size, int flags)
662665
}
663666
}
664667

668+
if (key == IPC_PRIVATE) {
669+
/* This should call shm_get with a brand new key id that isn't used yet. See https://man7.org/linux/man-pages/man2/shmget.2.html
670+
* Because shmop_open can be used in userland to attach to shared memory segments, use high positive numbers to avoid accidentally conflicting with userland. */
671+
key = (php_rand() & 0x3fffffff) + 0x40000000;
672+
for (shm_pair *ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) {
673+
if (ptr->descriptor && ptr->descriptor->shm_perm.key == key) {
674+
key = (php_rand() & 0x3fffffff) + 0x40000000;
675+
ptr = TWG(shm);
676+
continue;
677+
}
678+
}
679+
}
680+
665681
shm = shm_get(key, NULL);
666682
if (!shm) {
667683
CloseHandle(shm_handle);

0 commit comments

Comments
 (0)