Fix #73060: php failed with error after temp folder cleaned up

Instead of storing the mapping base address and the address of
`execute_ex()` in a separate file in the temporary folder, we store
them right at the beginning of the memory mapping.
This commit is contained in:
Christoph M. Becker 2020-07-29 15:11:04 +02:00
parent f8ff8bb767
commit 2bcc419800
2 changed files with 17 additions and 58 deletions

4
NEWS
View File

@ -12,6 +12,10 @@ PHP NEWS
- LDAP:
. Fixed memory leaks. (ptomulik)
- OPcache:
. Fixed bug #73060 (php failed with error after temp folder cleaned up).
(cmb)
06 Aug 2020, PHP 7.4.9
- Apache:

View File

@ -33,10 +33,11 @@
#define ACCEL_FILEMAP_NAME "ZendOPcache.SharedMemoryArea"
#define ACCEL_MUTEX_NAME "ZendOPcache.SharedMemoryMutex"
#define ACCEL_FILEMAP_BASE_DEFAULT 0x01000000
#define ACCEL_FILEMAP_BASE "ZendOPcache.MemoryBase"
#define ACCEL_EVENT_SOURCE "Zend OPcache"
/* address of mapping base and address of execute_ex */
#define ACCEL_BASE_POINTER_SIZE (2 * sizeof(void*))
static HANDLE memfile = NULL, memory_mutex = NULL;
static void *mapping_base;
@ -75,22 +76,6 @@ static char *create_name_with_username(char *name)
return newname;
}
static char *get_mmap_base_file(void)
{
static char windir[MAXPATHLEN+ 32 + 3 + sizeof("\\\\@") + 1 + 32 + 21];
int l;
GetTempPath(MAXPATHLEN, windir);
l = strlen(windir);
if ('\\' == windir[l-1]) {
l--;
}
snprintf(windir + l, sizeof(windir) - l - 1, "\\%s@%.32s@%.20s@%.32s", ACCEL_FILEMAP_BASE, accel_uname_id, sapi_module.name, accel_system_id);
return windir;
}
void zend_shared_alloc_create_lock(void)
{
memory_mutex = CreateMutex(NULL, FALSE, create_name_with_username(ACCEL_MUTEX_NAME));
@ -119,39 +104,20 @@ static int zend_shared_alloc_reattach(size_t requested_size, char **error_in)
{
int err;
void *wanted_mapping_base;
char *mmap_base_file = get_mmap_base_file();
FILE *fp = fopen(mmap_base_file, "r");
MEMORY_BASIC_INFORMATION info;
void *execute_ex_base;
int execute_ex_moved;
if (!fp) {
err = GetLastError();
zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err);
zend_win_error_message(ACCEL_LOG_FATAL, "Unable to open base address file", err);
*error_in="fopen";
return ALLOC_FAILURE;
}
if (!fscanf(fp, "%p", &wanted_mapping_base)) {
mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, ACCEL_BASE_POINTER_SIZE, NULL);
if (mapping_base == NULL) {
err = GetLastError();
zend_win_error_message(ACCEL_LOG_FATAL, "Unable to read base address", err);
*error_in="read mapping base";
fclose(fp);
return ALLOC_FAILURE;
}
if (!fscanf(fp, "%p", &execute_ex_base)) {
err = GetLastError();
zend_win_error_message(ACCEL_LOG_FATAL, "Unable to read execute_ex base address", err);
*error_in="read execute_ex base";
fclose(fp);
return ALLOC_FAILURE;
}
fclose(fp);
if (0 > win32_utime(mmap_base_file, NULL)) {
err = GetLastError();
zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err);
}
wanted_mapping_base = ((void**)mapping_base)[0];
execute_ex_base = ((void**)mapping_base)[1];
UnmapViewOfFile(mapping_base);
execute_ex_moved = (void *)execute_ex != execute_ex_base;
@ -207,7 +173,7 @@ static int zend_shared_alloc_reattach(size_t requested_size, char **error_in)
}
return ALLOC_FAIL_MAPPING;
}
smm_shared_globals = (zend_smm_shared_globals *) mapping_base;
smm_shared_globals = (zend_smm_shared_globals *) ((char*)mapping_base + ACCEL_BASE_POINTER_SIZE);
return SUCCESSFULLY_REATTACHED;
}
@ -325,23 +291,12 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_
*error_in = "MapViewOfFile";
return ALLOC_FAILURE;
} else {
char *mmap_base_file = get_mmap_base_file();
void *execute_ex_base = (void *)execute_ex;
FILE *fp = fopen(mmap_base_file, "w");
if (!fp) {
err = GetLastError();
zend_shared_alloc_unlock_win32();
zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err);
zend_win_error_message(ACCEL_LOG_FATAL, "Unable to write base address", err);
return ALLOC_FAILURE;
}
fprintf(fp, "%p\n", mapping_base);
fprintf(fp, "%p\n", execute_ex_base);
fclose(fp);
((void**)mapping_base)[0] = mapping_base;
((void**)mapping_base)[1] = (void*)execute_ex;
}
shared_segment->pos = 0;
shared_segment->size = requested_size;
shared_segment->pos = ACCEL_BASE_POINTER_SIZE;
shared_segment->size = requested_size - ACCEL_BASE_POINTER_SIZE;
zend_shared_alloc_unlock_win32();