Skip to content

array_walk($ffiInstance, function () {}) and reset($ffiInstance) crashes due to expecting mutable array #9697

Closed
@TysonAndre

Description

@TysonAndre

Description

The following code:

<?php
$x = FFI::new('int');
array_walk($x, function($x) { echo "test\n"; });

Resulted in this output:

segmentation fault (core dumped)

valgrind output:

==73944== Process terminating with default action of signal 11 (SIGSEGV)
==73944==  Bad permissions for mapped region at address 0x1D0352A
==73944==    at 0xA8A598: zend_hash_iterator_add (zend_hash.c:503)
==73944==    by 0x840B07: php_array_walk (array.c:1286)
==73944==    by 0x84183B: zif_array_walk (array.c:1407)
==73944==    by 0xAB4919: ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:1250)
==73944==    by 0xB2B883: execute_ex (zend_vm_execute.h:55975)
==73944==    by 0xB310D5: zend_execute (zend_vm_execute.h:60343)
==73944==    by 0xA73DE2: zend_execute_scripts (zend.c:1780)
==73944==    by 0x9CD491: php_execute_script (main.c:2480)
==73944==    by 0xBEDD26: do_cli (php_cli.c:964)
==73944==    by 0xBEE9E5: main (php_cli.c:1333)

But I expected this output instead:

// blank output

To fix this:
array_walk expects get_properties to return a non-empty refcounted array. Options include:

  1. Start doing that, e.g. with rebuild_object_properties. Also start to override the get_properties_for handler alongside the get_properties handler to return null
  2. Change behavior of that and other callers of Z_OBJPROP and other uses of get_properties to allow internal classes to return null in handler overrides
  3. Special case zend_hash_num_elements(target_hash) == 0 and return early while continuing to free userdata - this should avoid this crash?
// ext/standard/array.c
// static int php_array_walk(
// 	php_array_walk_context *context, zval *array, zval *userdata, int recursive)
	zend_hash_internal_pointer_reset_ex(target_hash, &pos);
	ht_iter = zend_hash_iterator_add(target_hash, pos); // this tries to modify the immutable array
// ext/ffi/ffi.c
static HashTable *zend_fake_get_properties(zend_object *obj) /* {{{ */
{
	return (HashTable*)&zend_empty_array;  // This is a const immutable array
}
/* }}} */

PHP Version

7.4-8.3-dev

Operating System

Any

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions