diff --git a/ext/ffi/ffi.g b/ext/ffi/ffi.g index d70075267e54f..3648372428900 100644 --- a/ext/ffi/ffi.g +++ b/ext/ffi/ffi.g @@ -264,12 +264,14 @@ struct_contents(zend_ffi_dcl *dcl): struct_declaration(zend_ffi_dcl *struct_dcl): {zend_ffi_dcl common_field_dcl = ZEND_FFI_ATTR_INIT;} + {zend_ffi_dcl base_field_dcl = ZEND_FFI_ATTR_INIT;} specifier_qualifier_list(&common_field_dcl) + {base_field_dcl = common_field_dcl;} ( /* empty */ {zend_ffi_add_anonymous_field(struct_dcl, &common_field_dcl);} | struct_declarator(struct_dcl, &common_field_dcl) ( "," - {zend_ffi_dcl field_dcl = common_field_dcl;} + {zend_ffi_dcl field_dcl = base_field_dcl;} attributes(&field_dcl)? struct_declarator(struct_dcl, &field_dcl) )* diff --git a/ext/ffi/ffi_parser.c b/ext/ffi/ffi_parser.c index 2589ae81e0259..26d623a40290e 100644 --- a/ext/ffi/ffi_parser.c +++ b/ext/ffi/ffi_parser.c @@ -2472,14 +2472,16 @@ static int parse_struct_contents(int sym, zend_ffi_dcl *dcl) { static int parse_struct_declaration(int sym, zend_ffi_dcl *struct_dcl) { zend_ffi_dcl common_field_dcl = ZEND_FFI_ATTR_INIT; + zend_ffi_dcl base_field_dcl = ZEND_FFI_ATTR_INIT; sym = parse_specifier_qualifier_list(sym, &common_field_dcl); + base_field_dcl = common_field_dcl; if (sym == YY__SEMICOLON || sym == YY__RBRACE) { zend_ffi_add_anonymous_field(struct_dcl, &common_field_dcl); } else if (sym == YY__STAR || sym == YY_ID || sym == YY__LPAREN || sym == YY__COLON) { sym = parse_struct_declarator(sym, struct_dcl, &common_field_dcl); while (sym == YY__COMMA) { sym = get_sym(); - zend_ffi_dcl field_dcl = common_field_dcl; + zend_ffi_dcl field_dcl = base_field_dcl; if (YY_IN_SET(sym, (YY___ATTRIBUTE,YY___ATTRIBUTE__,YY___DECLSPEC,YY___CDECL,YY___STDCALL,YY___FASTCALL,YY___THISCALL,YY___VECTORCALL), "\000\000\000\000\000\000\360\017\000\000\000\000\000")) { sym = parse_attributes(sym, &field_dcl); } diff --git a/ext/ffi/tests/ptr_declaration_list.phpt b/ext/ffi/tests/ptr_declaration_list.phpt new file mode 100644 index 0000000000000..cb8ecafd935ba --- /dev/null +++ b/ext/ffi/tests/ptr_declaration_list.phpt @@ -0,0 +1,33 @@ +--TEST-- +Declaration Lists with Pointers +--EXTENSIONS-- +ffi +--SKIPIF-- +--FILE-- +new('struct MyStruct'); +$one = $ffi->new("uint8_t"); +$oneptr = $ffi->new("uint8_t*"); +$oneptrptr = $ffi->new("uint8_t**"); +$one->cdata = 1; +$oneptr = FFI::addr($one); +$oneptrptr = FFI::addr($oneptr); + +$test_struct->a = $oneptrptr; +$test_struct->b = $oneptr; +$test_struct->c = $one; + +var_dump($test_struct->a[0][0]); +var_dump($test_struct->b[0]); +var_dump($test_struct->c); +?> +--EXPECT-- +int(1) +int(1) +int(1)