From 59a680dfcb1f2a459d253cd3031ac0a3f74a683c Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 7 May 2020 12:32:10 +0200 Subject: [PATCH] Fix #79571: FFI: var_dumping unions may segfault We must not attempt to access arbitrary union members when retrieving debug info, because that may not be valid. We report unions as empty instead. --- ext/ffi/ffi.c | 24 +++++++++++++----------- ext/ffi/tests/bug79571.phpt | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 ext/ffi/tests/bug79571.phpt diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 9626c4b374827..60b7419bd43b4 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -1987,18 +1987,20 @@ static HashTable *zend_ffi_cdata_get_debug_info(zval *object, int *is_temp) /* { break; case ZEND_FFI_TYPE_STRUCT: ht = zend_new_array(zend_hash_num_elements(&type->record.fields)); - ZEND_HASH_FOREACH_STR_KEY_PTR(&type->record.fields, key, f) { - if (key) { - if (!f->bits) { - void *f_ptr = (void*)(((char*)ptr) + f->offset); - zend_ffi_cdata_to_zval(NULL, f_ptr, ZEND_FFI_TYPE(f->type), BP_VAR_R, &tmp, ZEND_FFI_FLAG_CONST, 0); - zend_hash_add(ht, key, &tmp); - } else { - zend_ffi_bit_field_to_zval(ptr, f, &tmp); - zend_hash_add(ht, key, &tmp); + if (!(type->attr & ZEND_FFI_ATTR_UNION)) { + ZEND_HASH_FOREACH_STR_KEY_PTR(&type->record.fields, key, f) { + if (key) { + if (!f->bits) { + void *f_ptr = (void*)(((char*)ptr) + f->offset); + zend_ffi_cdata_to_zval(NULL, f_ptr, ZEND_FFI_TYPE(f->type), BP_VAR_R, &tmp, ZEND_FFI_FLAG_CONST, 0); + zend_hash_add(ht, key, &tmp); + } else { + zend_ffi_bit_field_to_zval(ptr, f, &tmp); + zend_hash_add(ht, key, &tmp); + } } - } - } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } *is_temp = 1; return ht; case ZEND_FFI_TYPE_ARRAY: diff --git a/ext/ffi/tests/bug79571.phpt b/ext/ffi/tests/bug79571.phpt new file mode 100644 index 0000000000000..008870ca63578 --- /dev/null +++ b/ext/ffi/tests/bug79571.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #79571 (FFI: var_dumping unions may segfault) +--SKIPIF-- + +--FILE-- +new('my_union'); +$union->num = 42; +var_dump($union); +var_dump($union->num); +?> +--EXPECTF-- +object(FFI\CData:union )#%d (0) { +} +int(42)