microsoft / mimalloc

mimalloc is a compact general purpose allocator with excellent performance.
MIT License
10.57k stars 860 forks source link

PHP Failing to free(), Stating Invalid Pointers #377

Open lzlrd opened 3 years ago

lzlrd commented 3 years ago

PHP (at the very least PHP 5.6, PHP 7.4, and PHP 8.0) seems to be incompatible with mimalloc and faults after each command. Interestingly, most CLI commands are able to successfully provide their output but then fault at the end. The anomaly is php --help which doesn't fault or error out. This occurs with both Secure Mode Mimalloc and "Normal" Mimalloc.

The problem seems to lie in munmap_chunk(), according to the following verbose output:

mimalloc: process init: 0x7f7e28dceb80
mimalloc: secure level: 4
mimalloc: using 1 numa regions
mimalloc: option 'show_errors': 0
mimalloc: option 'show_stats': 1
mimalloc: option 'eager_commit': 1
mimalloc: option 'eager_region_commit': 1
mimalloc: option 'reset_decommits': 0
mimalloc: option 'large_os_pages': 0
mimalloc: option 'reserve_huge_os_pages': 0
mimalloc: option 'segment_cache': 0
mimalloc: option 'page_reset': 1
mimalloc: option 'abandoned_page_reset': 0
mimalloc: option 'segment_reset': 0
mimalloc: option 'eager_commit_delay': 1
mimalloc: option 'reset_delay': 100
mimalloc: option 'use_numa_nodes': 0
mimalloc: option 'os_tag': 100
mimalloc: option 'max_errors': 16
munmap_chunk(): invalid pointer
Aborted (core dumped)

I assume this then causes free() to fail:

mimalloc: process init: 0x7fb2802d6b80
mimalloc: secure level: 4
mimalloc: using 1 numa regions
mimalloc: option 'show_errors': 0
mimalloc: option 'show_stats': 0
mimalloc: option 'eager_commit': 1
mimalloc: option 'eager_region_commit': 1
mimalloc: option 'reset_decommits': 0
mimalloc: option 'large_os_pages': 0
mimalloc: option 'reserve_huge_os_pages': 0
mimalloc: option 'segment_cache': 0
mimalloc: option 'page_reset': 1
mimalloc: option 'abandoned_page_reset': 0
mimalloc: option 'segment_reset': 0
mimalloc: option 'eager_commit_delay': 1
mimalloc: option 'reset_delay': 100
mimalloc: option 'use_numa_nodes': 0
mimalloc: option 'os_tag': 100
mimalloc: option 'max_errors': 16
free(): invalid pointer
Aborted (core dumped)

However, I'm also able to have mimalloc fault with a double free at other times:

mimalloc: process init: 0x7f9d6aa95b80
mimalloc: secure level: 4
mimalloc: using 1 numa regions
mimalloc: option 'show_errors': 0
mimalloc: option 'show_stats': 0
mimalloc: option 'eager_commit': 1
mimalloc: option 'eager_region_commit': 1
mimalloc: option 'reset_decommits': 0
mimalloc: option 'large_os_pages': 0
mimalloc: option 'reserve_huge_os_pages': 0
mimalloc: option 'segment_cache': 0
mimalloc: option 'page_reset': 1
mimalloc: option 'abandoned_page_reset': 0
mimalloc: option 'segment_reset': 0
mimalloc: option 'eager_commit_delay': 1
mimalloc: option 'reset_delay': 100
mimalloc: option 'use_numa_nodes': 0
mimalloc: option 'os_tag': 100
mimalloc: option 'max_errors': 16
double free or corruption (out)
Aborted (core dumped)

This is likely the same bug affecting https://github.com/microsoft/mimalloc/issues/345.


This has been tested across two installations on Arch Linux using LD_PRELOAD and /etc/ld.so.preload to override PHP's usage of the default/in-built allocator.

lzlrd commented 3 years ago

Update: I've tried https://github.com/mjansson/rpmalloc and https://github.com/google/tcmalloc, but PHP also seems to fail. However, jemalloc works fine:

$ LD_PRELOAD=/usr/lib/libmimalloc.so php
free(): invalid pointer
Aborted (core dumped)

$ LD_PRELOAD=/usr/lib/libmimalloc-secure.so php
munmap_chunk(): invalid pointer
Aborted (core dumped)

$ LD_PRELOAD=/home/lazerl0rd/librpmallocwrap.so php
free(): invalid pointer
Aborted (core dumped)

$ LD_PRELOAD=/usr/lib/libtcmalloc.so php
double free or corruption (out)
Aborted (core dumped)

$ LD_PRELOAD=/usr/lib/libjemalloc.so php
ac000 commented 2 years ago

jemalloc fails for me on Fedora 35

$ rpm -q jemalloc php-cli
jemalloc-5.2.1-6.fc35.x86_64
php-cli-8.0.18-1.fc35.x86_64

$ LD_PRELOAD=/lib64/libjemalloc.so.2 php
free(): invalid pointer
Aborted (core dumped)
simaotwx commented 1 year ago

Can confirm. Same issue on 8.1.16, apache2 variant:

free(): invalid pointer