Bug #77194 [Com]: php7ts.dll crashing when running embed

From: Date: Fri, 07 Dec 2018 11:01:55 +0000
Subject: Bug #77194 [Com]: php7ts.dll crashing when running embed
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-218309@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=77194&edit=1

 ID:                 77194
 Comment by:         jr at concept-br dot de
 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:

Same Problem here also in 7.2.13 on Windows Server 2012 R2. We restart the apache service every hour
to "workaround" until a bugfix is released


Previous Comments:
------------------------------------------------------------------------
[2018-11-29 16:49:12] svbussww at 126 dot com

I have uploaded a fix.
Use _aligned_malloc and _aligned_free instead of unreliable VirtualAlloc and VirtualFree

------------------------------------------------------------------------
[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

------------------------------------------------------------------------


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


Thread (22 messages)

« previous php.bugs (#218309) next »