bitwiseworks / libcx

kLIBC Extension Library
GNU Lesser General Public License v2.1
11 stars 1 forks source link

munmap fails with assertion error 487 when DosFreeMem fails #71

Closed StevenLevine closed 3 years ago

StevenLevine commented 5 years ago

This issue was detected while porting php 7.x. The external symptoms are that a libcx assertion fails with:

Opened log at 2019-09-07 19:59:50.59 Process ID: 0x2b45 (11077) Parent PID: 0x1b (27) Type: 2 Exe hmte : 0x245e (D:\INTERNET\PHP7\PHP.EXE) First arg : D:\Internet\php7\php.exe Second arg: -c ./php7.ini --version Cur dir : D:\Internet\php7 CRT Module: LIBCN0 hmod=0xe23 (D:\USR\LIB\LIBCN0.DLL) __libc_logInit: addr 0x1d2850ed iObj=0 offObj=0x450ed Millsecond Timestamp. | Thread ID. | | Call Nesting Level. | | | Log Group. | | | | Message Type. | | | | | errno in hex (0xface if not available). | | | | | | Function Name. | | | | | | | Millisconds In function (Optional). v v v v v v v v xxxxxxxx tt nn gggg dddd eeee function [(ms)]: message LIBCx version : 0.6.6 LIBCx module : D:\USR\LIB\LIBCX0.DLL (hmod=2bc6) 1a93197f 01 ff 0000 Asrt: Assertion Failed!!! 1a93197f 01 ff 0000 Asrt: Function: 1a93197f 01 ff 0000 Asrt: File: D:/Users/dmik/rpmbuild/BUILD/libcx-0.6.6/src/mmap/mmap.c 1a93197f 01 ff 0000 Asrt: Line: 1257 1a93197f 01 ff 0000 Asrt: Expr: arc == NO_ERROR 1a93197f 01 ff 0000 Asrt: 487

The reason the assertion triggered is because DosFreeMem was asked free a block that was not allocated by DosAllocMem

php's zend wants a 2MB object aligned on a 2MB boundary for its private heap, so it does:

0x21030000 = mmap(0x200000)

However since this address is not on a 2MB boundary, php unmaps the object with

munmap(0x21030000, 0x200000)

and allocates a 2MB + 2MB - 4KB object with

0x21030000 = mmap(0x3FF000)

and calculates the aligned address of the aligned heap object within the allocated object as

0x21200000

Next php unmaps the memory before the object with

munmap(0x21030000, 0x1D0000)

and unmaps the memory after the object with

munmap(0x21400000, 0x2F000)

The result is a usable 2MB aligned heap object starting at 0x21200000.

Everything is fine until php attempts to shut down. The destructor attempts to unmap the aligned 2MB heap with

munmap(0x21200000,0x200000)

and libcx notices that the ref count has gone to zero and attempts to free the allocated memory with

DosFreeMem(0x21200000)

The fails with error 487 because this is not the correct address. Libcx should have freed the allocated memory with

DosFreeMem(0x21030000)

because this was the address returned by the original DosAllocMem.

dmik commented 5 years ago

Steven, great report! Should be easy to fix, will look at it soon.

dmik commented 3 years ago

Appears that I fixed this back in 2020 while working for Chromium, see 09b0eaa459fe7b3f2c61eb670d8f56c8c0a29ad2.

Closing. Feel free to reopen if the problem reappears.

dmik commented 3 years ago

Also linking this to #75 and #76 which are related.