Edit report at https://bugs.php.net/bug.php?id=77194&edit=1
ID: 77194
User updated by: svbussww at 126 dot com
Reported by: svbussww at 126 dot com
Summary: php7ts.dll crashing when running embed
Status: Open
Type: Bug
Package: Reproducible crash
Operating System: Windows 7
PHP Version: 7.2.12
Block user comment: N
Private report: N
New Comment:
I have uploaded a fix.
Use _aligned_malloc and _aligned_free instead of unreliable VirtualAlloc and VirtualFree
Previous Comments:
------------------------------------------------------------------------
[2018-11-27 13:41:27] svbussww at 126 dot com
Fix the temporary plan
static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
{
void *ptr = zend_mm_mmap(size);
if (ptr == NULL) {
return NULL;
} else if (ZEND_MM_ALIGNED_OFFSET(ptr, alignment) == 0) {
#ifdef MADV_HUGEPAGE
madvise(ptr, size, MADV_HUGEPAGE);
#endif
return ptr;
} else {
size_t offset;
/* chunk has to be aligned */
zend_mm_munmap(ptr, size);
LOOP:;
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
if (ptr == NULL) return NULL;
#ifdef _WIN32
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
ptr = zend_mm_mmap_fixed((void*)((char*)ptr + (alignment - offset)), size);
if(ptr == NULL) goto LOOP;
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
if (offset != 0) {
zend_mm_munmap(ptr, size);
return NULL;
}
return ptr;
#else
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
if (offset != 0) {
offset = alignment - offset;
zend_mm_munmap(ptr, offset);
ptr = (char*)ptr + offset;
alignment -= offset;
}
if (alignment > REAL_PAGE_SIZE) {
zend_mm_munmap((char*)ptr + size, alignment - REAL_PAGE_SIZE);
}
# ifdef MADV_HUGEPAGE
madvise(ptr, size, MADV_HUGEPAGE);
# endif
#endif
return ptr;
}
}
------------------------------------------------------------------------
[2018-11-27 12:46:17] svbussww at 126 dot com
The bug has been found
file Zend/zend_alloc.c
function zend_mm_chunk_alloc_int
zend_mm_mmap After not aligned
zend_mm_mmap_fixed Call failed is return 0
The cause of the bug
zend_mm_mmap The allocated memory address is released. In the case of multithreading, it may be
preempted by other threads.
This causes the subsequent zend_mm_mmap_fixed function to allocate memory and cause the program to
crash.
Temporary solution
static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
{
LOOP:;
void *ptr = zend_mm_mmap(size);
if (ptr == NULL) {
return NULL;
} else if (ZEND_MM_ALIGNED_OFFSET(ptr, alignment) == 0) {
#ifdef MADV_HUGEPAGE
madvise(ptr, size, MADV_HUGEPAGE);
#endif
return ptr;
} else {
size_t offset;
/* chunk has to be aligned */
zend_mm_munmap(ptr, size);
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
#ifdef _WIN32
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
ptr = zend_mm_mmap_fixed((void*)((char*)ptr + (alignment - offset)), size);
if(ptr == NULL) goto LOOP;
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
if (offset != 0) {
zend_mm_munmap(ptr, size);
return NULL;
}
return ptr;
#else
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
if (offset != 0) {
offset = alignment - offset;
zend_mm_munmap(ptr, offset);
ptr = (char*)ptr + offset;
alignment -= offset;
}
if (alignment > REAL_PAGE_SIZE) {
zend_mm_munmap((char*)ptr + size, alignment - REAL_PAGE_SIZE);
}
# ifdef MADV_HUGEPAGE
madvise(ptr, size, MADV_HUGEPAGE);
# endif
#endif
return ptr;
}
}
I hope the development team can solve this bug as soon as possible.
------------------------------------------------------------------------
[2018-11-27 12:03:08] svbussww at 126 dot com
Can't initialize heap: [0x000001e7] Attempt to access invalid address.
Tracking source code is generated from zend_alloc.c
in zend_mm_mmap_fixed
VirtualAlloc Error return NULL
------------------------------------------------------------------------
[2018-11-26 22:16:52] svbussww at 126 dot com
The problem persists after using the standard method
Environment is Windows 7 SP1 + VS2017 Enterprise
Test code
DWORD WINAPI ThreadProc(LPVOID lpParameter) {
ts_resource(0);
ts_free_thread();
return 0;
}
int main(){
php_embed_init(0, NULL);
for (;;){
HANDLE Thread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
if (Thread != NULL) CloseHandle(Thread);
}
php_embed_shutdown();
return 0;
}
Debug
Problem event name: APPCRASH
Application Name: Test.exe
Application version: 0.0.0.0
Application timestamp: 5bfc6f7c
Fault module name: php7ts.dll
Fault module version: 7.2.12.0
Fault module timestamp: 5be3d4fd
Exception code: c0000005
Abnormal offset: 000000000001f648
OS version: 6.1.7601.2.1.0.256.1
Locale ID: 2052
Other information 1:e3c7
Additional information 2:e3c7d0ab13feedaa62f1ab674aea779c
Other information 3: db03
Other information 4: db03925cc4db17c3dff9789e6103f141
Can't initialize heap: [0x000001e7] Attempt to access invalid address.
Exception thrown at 0x000007FEEAD5F648 (in php7ts.dll) (in Test.exe): 0xC0000005: An access
violation occurred while reading location 0x0000000000000000.
Stack
php7ts.dll!_emalloc(unsigned __int64 size) Line 2425
php7ts.dll!cwd_globals_ctor(_virtual_cwd_globals * cwd_g) Line 391
php7ts.dll!allocate_new_resource(_tsrm_tls_entry * * thread_resources_ptr, unsigned long thread_id)
Line 315
php7ts.dll!ts_resource_ex(int id, unsigned long * th_id) Line 395
Test.exe!ThreadProc(void * lpParameter) Line 9
------------------------------------------------------------------------
[2018-11-26 21:21:01] svbussww at 126 dot com
Since my test code is completely from php_embed.c and checked correctly
So in theory, using php7embed.lib should also have this problem.
I will go through the standard usage test, but I still hope that I can pay attention to it.
If the standard method still exists, I will follow up the feedback.
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=77194
--
Edit this bug report at https://bugs.php.net/bug.php?id=77194&edit=1