diff --git a/NEWS b/NEWS index e61ca38dedb..efe09709aae 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,10 @@ PHP NEWS . Fixed case when curl_error returns an empty string. (David Carlier) +- FFI: + . Fixed bug GH-14286 (ffi enum type (when enum has no name) make memory + leak). (nielsdos, dstogov) + - Soap: . Fixed bug #55639 (Digest autentication dont work). (nielsdos) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index bbfe07576e6..86da8211ef2 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -3582,7 +3582,7 @@ ZEND_METHOD(FFI, scope) /* {{{ */ } /* }}} */ -static void zend_ffi_cleanup_dcl(zend_ffi_dcl *dcl) /* {{{ */ +void zend_ffi_cleanup_dcl(zend_ffi_dcl *dcl) /* {{{ */ { if (dcl) { zend_ffi_type_dtor(dcl->type); diff --git a/ext/ffi/ffi.g b/ext/ffi/ffi.g index e30d86b21c7..d70075267e5 100644 --- a/ext/ffi/ffi.g +++ b/ext/ffi/ffi.g @@ -97,7 +97,10 @@ declarations: initializer? {zend_ffi_declare(name, name_len, &dcl);} )* - )? + | + /* empty */ + {if (common_dcl.flags & (ZEND_FFI_DCL_ENUM | ZEND_FFI_DCL_STRUCT | ZEND_FFI_DCL_UNION)) zend_ffi_cleanup_dcl(&common_dcl);} + ) ";" )* ; diff --git a/ext/ffi/ffi_parser.c b/ext/ffi/ffi_parser.c index 8d06f1d8758..2589ae81e02 100644 --- a/ext/ffi/ffi_parser.c +++ b/ext/ffi/ffi_parser.c @@ -2115,6 +2115,10 @@ static int parse_declarations(int sym) { } zend_ffi_declare(name, name_len, &dcl); } + } else if (sym == YY__SEMICOLON) { + if (common_dcl.flags & (ZEND_FFI_DCL_ENUM | ZEND_FFI_DCL_STRUCT | ZEND_FFI_DCL_UNION)) zend_ffi_cleanup_dcl(&common_dcl); + } else { + yy_error_sym("unexpected", sym); } if (sym != YY__SEMICOLON) { yy_error_sym("';' expected, got", sym); diff --git a/ext/ffi/php_ffi.h b/ext/ffi/php_ffi.h index 02a241c6bb6..430b8a2e568 100644 --- a/ext/ffi/php_ffi.h +++ b/ext/ffi/php_ffi.h @@ -208,6 +208,7 @@ typedef struct _zend_ffi_val { zend_result zend_ffi_parse_decl(const char *str, size_t len); zend_result zend_ffi_parse_type(const char *str, size_t len, zend_ffi_dcl *dcl); +void zend_ffi_cleanup_dcl(zend_ffi_dcl *dcl); /* parser callbacks */ void ZEND_NORETURN zend_ffi_parser_error(const char *msg, ...); diff --git a/ext/ffi/tests/gh14286_1.phpt b/ext/ffi/tests/gh14286_1.phpt new file mode 100644 index 00000000000..19701f634a6 --- /dev/null +++ b/ext/ffi/tests/gh14286_1.phpt @@ -0,0 +1,46 @@ +--TEST-- +GH-14286 (ffi enum type (when enum has no name) make memory leak) +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 +--FILE-- +TEST_ONE); +var_dump($ffi->TEST_TWO); +var_dump($ffi->TEST_THREE); +var_dump($ffi->TEST_FOUR); +var_dump($ffi->TEST_FIVE); +var_dump($ffi->TEST_SIX); +?> +--EXPECT-- +int(1) +int(2) +int(3) +int(4) +int(5) +int(6) diff --git a/ext/ffi/tests/gh14286_2.phpt b/ext/ffi/tests/gh14286_2.phpt new file mode 100644 index 00000000000..683929780c0 --- /dev/null +++ b/ext/ffi/tests/gh14286_2.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-14286 (ffi enum type (when enum has no name) make memory leak) +--EXTENSIONS-- +ffi +--SKIPIF-- + +--INI-- +ffi.enable=1 +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +Failed resolving C variable 'x'