-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Do not delete main chunk in zend_gc #18756
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
base: PHP-8.3
Are you sure you want to change the base?
Conversation
On first sight it seems right but I would need to make myself more familiar with zend_alloc first to say for sure. Do you also have a test for this? |
Calling zend_mm_gc twice in a row during the shutdown process (before the heap is freed obviously), or super early after it's created so it has no usage reproduces the issue. Currently using https://github.com/danog/php-src/tree/heap_validation to try and catch a heap corruption bug (#17974) that won't popup with ASAN (w/ the zend allocator enabled), this is were I found the issue. (Side note, the original #17974 issue seems to trigger when cleaning up the objects store, specifically when cleaning up a weakmap, currently debugging more to better reproduce that issue) |
I'm not really zend_alloc expert - should be more a ping for @arnaud-lb I guess :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I confirm the issue, and the fix looks good to me.
Here is a reproducer:
--- a/ext/zend_test/test.c
+++ b/ext/zend_test/test.c
@@ -1613,3 +1613,10 @@ static PHP_FUNCTION(zend_test_compile_to_ast)
RETVAL_STR(result);
}
+
+PHP_FUNCTION(zend_test_mm)
+{
+ zend_mm_heap *heap = zend_mm_startup();
+ zend_mm_gc(heap);
+ zend_mm_gc(heap);
+}
diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php
index 9923da6dcee..48be105d219 100644
--- a/ext/zend_test/test.stub.php
+++ b/ext/zend_test/test.stub.php
@@ -202,6 +202,8 @@ enum ZendTestIntEnum: int {
case Baz = -1;
}
+ function zend_test_mm(): void {}
+
function zend_test_array_return(): array {}
/** @genstubs-expose-comment-block
@@ -399,3 +401,4 @@ function namespaced_aliased_func(): void {}
*/
function namespaced_deprecated_aliased_func(): void {}
}
The first zend_mm_gc()
call deletes the main chunk, which shouldn't happen. The second call crashes because of that.
Zend/tests/gh18756.phpt
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be in ext/zend_test
and a --EXTENSION--
section for zend_test
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--EXTENSION--
section forzend_test
.
Indeed, my bad.
Should be in
ext/zend_test
Are you sure? I see ext/zend_test
as a set of APIs for testing underlying mechanisms that are outside of ext/zend_test
. Tests in ext/zend_test/tests
would be for testing zend_test
itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure?
No. What you say makes sense, boundaries are probably a little muddy 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good but needs a small fix in the test code (besides Tim's EXTENSIONS section remark)
@@ -1516,3 +1516,11 @@ static PHP_FUNCTION(zend_test_create_throwing_resource) | |||
zend_resource *res = zend_register_resource(NULL, le_throwing_resource); | |||
ZVAL_RES(return_value, res); | |||
} | |||
|
|||
PHP_FUNCTION(zend_test_gh18756) | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need ZEND_PARSE_PARAMETERS_NONE(); for the arginfo/zpp check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed (that's my mistake, not @danog's, I did push this test)
c58210c
to
33a2155
Compare
Fixes an issue where invoking zend_mm_gc twice with no allocations (and only one chunk, and no cached chunks) causes a segfault, because the first
zend_mm_gc
assigns NULL to thenext
property when copying the chunk to the (initially empty) cached chunks list, which breaks the main chunk list which expects a circular linked list instead of a null-terminated linked list.This matches the behavior of the other invocation of zend_mm_gc, which is also skipped when acting upon the main chunk.