-
Notifications
You must be signed in to change notification settings - Fork 7.9k
intl causing segfault in docker images #11874
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
As a workaround I had to convert the line foreach(\IntlTimeZone::createTimeZoneIDEnumeration(\IntlTimeZone::TYPE_ANY) as $id) { to foreach(iterator_to_array(\IntlTimeZone::createTimeZoneIDEnumeration(\IntlTimeZone::TYPE_ANY)) as $id) { Maybe this gives a hint to where the bug lies. |
The absolute minimal reproducer is one of these two, they both crash under ASAN: foreach(IntlCalendar::getKeywordValuesForLocale('calendar', 'fa_IR', true) as $id) {
debug_zval_dump($id);
} foreach(IntlTimeZone::createTimeZoneIDEnumeration(IntlTimeZone::TYPE_ANY) as $id) {
debug_zval_dump($id);
} It seems to crash because the refcount of an object drops to 0 while it's still referenced from somewhere. |
The segfault happens because zoi->wrapping_obj points to an object that has been freed. This wrapping_obj is set in IntlIterator_from_StringEnumeration(). Notice how the refcount is not increased in this function. By switching to ZVAL_OBJ_COPY, the segfault disappears. However, now we get memleaks. The reason we get a memleak is because now we're responsible for destroying the reference copy we made with ZVAL_OBJ_COPY. It would appear this would already be done in zoi_with_current_dtor. This did work in the past for CVs because the live variable cleanup when the CV gets destroyed would set the object to UNDEF. To add more confusion: The zoi_with_current_dtor() comments seem to indicate that it can be called twice. However, that seems to be _not_ the case as it's the dtor for zend_object_iterator_funcs. This patch reworks how the destruction works in addition to the ZVAL_OBJ_COPY change. I checked other of wrapping_obj. The only other place is in BreakIterator. BreakIterator doesn't actually use the wrapping_obj for anything however, and doesn't manage that refcount, so set it to UNDEF to be safe.
I can't figure it out, I made some progress in my PR but I'm stuck. I closed my PR, someone else feel free to work on this. |
The segfault happens because zoi->wrapping_obj points to an object that has been freed. This wrapping_obj is set in IntlIterator_from_StringEnumeration(). Notice how the refcount is not increased in this function. By switching to ZVAL_OBJ_COPY, the segfault disappears. We also need to move the responsibility of destroying the iterator to the iterator itself and keep the object data destruction in the object destruction. The existing code used a weird recursive destruction between the iterator and object that was too hard to understand to be honest. This patch simplifies everything and in the process gets rid of the leak. Iterators that are embedded are now responsible for their own memory cleanup.
* PHP-8.3: Fix GH-11874: intl causing segfault in docker images
* PHP-8.4: Fix GH-11874: intl causing segfault in docker images
The segfault happens because zoi->wrapping_obj points to an object that has been freed. This wrapping_obj is set in IntlIterator_from_StringEnumeration(). Notice how the refcount is not increased in this function. By switching to ZVAL_OBJ_COPY, the segfault disappears. We also need to move the responsibility of destroying the iterator to the iterator itself and keep the object data destruction in the object destruction. The existing code used a weird recursive destruction between the iterator and object that was too hard to understand to be honest. This patch simplifies everything and in the process gets rid of the leak. Iterators that are embedded are now responsible for their own memory cleanup. Closes phpGH-17343.
Description
I was not able to reproduce it with a simple code or any CLI execution, it only works when it is called through FPM or Apache docker images. I've made an example repository for reproduction that uses the official
php:8.2.8-apache
tag to produce the segfault.https://github.com/adrianrudnik/intl-segfault
It uses a simplified
index.php
,Dockerfile
andcomposer
forsymfony/intl
that got me the segfault.How to reproduce:
then open http://localhost:8080/ to trigger the following docker log entries:
GDB
and coredumps are configured and should be debuggable on the containers shell with (anddocker exec
):Output on my machine:
PHP Version
PHP 8.2.8
Operating System
Docker version 24.0.5, build ced0996. Pop!_OS 22.04 LTS
The text was updated successfully, but these errors were encountered: