Skip to content

Instantly share code, notes, and snippets.

@nielsdos
Last active May 21, 2024 21:28
Show Gist options
  • Save nielsdos/62016be38fff00f97bfbee4a430cc009 to your computer and use it in GitHub Desktop.
Save nielsdos/62016be38fff00f97bfbee4a430cc009 to your computer and use it in GitHub Desktop.
diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c
index 560338e71f3..8b0b58105d3 100644
--- a/ext/ffi/ffi.c
+++ b/ext/ffi/ffi.c
@@ -3544,7 +3544,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 b70e3f12996..ed073f269b4 100644
--- a/ext/ffi/ffi.g
+++ b/ext/ffi/ffi.g
@@ -136,7 +136,8 @@ declaration_specifiers(zend_ffi_dcl *dcl):
")"
| attributes(dcl)
| type_qualifier(dcl)
- | type_specifier(dcl)
+ | {bool standalone_type = !(dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS);}
+ type_specifier(dcl, standalone_type)
)
)+
;
@@ -144,7 +145,7 @@ declaration_specifiers(zend_ffi_dcl *dcl):
specifier_qualifier_list(zend_ffi_dcl *dcl):
"__extension__"?
( ?{sym != YY_ID || zend_ffi_is_typedef_name((const char*)yy_text, yy_pos - yy_text) || (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) == 0}
- ( type_specifier(dcl)
+ ( type_specifier(dcl, false)
| type_qualifier(dcl)
| attributes(dcl)
)
@@ -169,7 +170,7 @@ type_qualifier(zend_ffi_dcl *dcl):
{dcl->flags |= ZEND_FFI_DCL_ATOMIC;}
;
-type_specifier(zend_ffi_dcl *dcl):
+type_specifier(zend_ffi_dcl *dcl, bool standalone_type):
{const char *name;}
{size_t name_len;}
( {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);}
@@ -216,7 +217,7 @@ type_specifier(zend_ffi_dcl *dcl):
| {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);}
struct_or_union_specifier(dcl)
| {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);}
- enum_specifier(dcl)
+ enum_specifier(dcl, standalone_type)
| {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);}
{/*redeclaration of '%.*s' ??? */}
ID(&name, &name_len)
@@ -291,7 +292,7 @@ struct_declarator(zend_ffi_dcl *struct_dcl, zend_ffi_dcl *field_dcl):
)
;
-enum_specifier(zend_ffi_dcl *dcl):
+enum_specifier(zend_ffi_dcl *dcl, bool standalone_type):
"enum"
{dcl->flags |= ZEND_FFI_DCL_ENUM;}
attributes(dcl)?
@@ -310,6 +311,7 @@ enum_specifier(zend_ffi_dcl *dcl):
enumerator_list(dcl)
"}"
attributes(dcl)?+
+ {if (standalone_type) zend_ffi_cleanup_dcl(dcl);}
)
;
diff --git a/ext/ffi/ffi_parser.c b/ext/ffi/ffi_parser.c
index b956f885ee0..4f024c457a0 100644
--- a/ext/ffi/ffi_parser.c
+++ b/ext/ffi/ffi_parser.c
@@ -259,12 +259,12 @@ static int parse_declaration_specifiers(int sym, zend_ffi_dcl *dcl);
static int parse_specifier_qualifier_list(int sym, zend_ffi_dcl *dcl);
static int parse_type_qualifier_list(int sym, zend_ffi_dcl *dcl);
static int parse_type_qualifier(int sym, zend_ffi_dcl *dcl);
-static int parse_type_specifier(int sym, zend_ffi_dcl *dcl);
+static int parse_type_specifier(int sym, zend_ffi_dcl *dcl, bool standalone_type);
static int parse_struct_or_union_specifier(int sym, zend_ffi_dcl *dcl);
static int parse_struct_contents(int sym, zend_ffi_dcl *dcl);
static int parse_struct_declaration(int sym, zend_ffi_dcl *struct_dcl);
static int parse_struct_declarator(int sym, zend_ffi_dcl *struct_dcl, zend_ffi_dcl *field_dcl);
-static int parse_enum_specifier(int sym, zend_ffi_dcl *dcl);
+static int parse_enum_specifier(int sym, zend_ffi_dcl *dcl, bool standalone_type);
static int parse_enumerator_list(int sym, zend_ffi_dcl *enum_dcl);
static int parse_enumerator(int sym, zend_ffi_dcl *enum_dcl, int64_t *min, int64_t *max, int64_t *last);
static int parse_declarator(int sym, zend_ffi_dcl *dcl, const char **name, size_t *name_len);
@@ -2165,7 +2165,8 @@ static int parse_declaration_specifiers(int sym, zend_ffi_dcl *dcl) {
case YY_UNION:
case YY_ENUM:
case YY_ID:
- sym = parse_type_specifier(sym, dcl);
+ bool standalone_type = !(dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS);
+ sym = parse_type_specifier(sym, dcl, standalone_type);
break;
default:
yy_error_sym("unexpected", sym);
@@ -2180,7 +2181,7 @@ static int parse_specifier_qualifier_list(int sym, zend_ffi_dcl *dcl) {
}
do {
if (YY_IN_SET(sym, (YY_VOID,YY_CHAR,YY_SHORT,YY_INT,YY_LONG,YY_FLOAT,YY_DOUBLE,YY_SIGNED,YY_UNSIGNED,YY__BOOL,YY__COMPLEX,YY_COMPLEX,YY___COMPLEX,YY___COMPLEX__,YY_STRUCT,YY_UNION,YY_ENUM,YY_ID), "\000\000\000\370\377\107\000\000\000\000\000\002\000")) {
- sym = parse_type_specifier(sym, dcl);
+ sym = parse_type_specifier(sym, dcl, false);
} else if (YY_IN_SET(sym, (YY_CONST,YY___CONST,YY___CONST__,YY_RESTRICT,YY___RESTRICT,YY___RESTRICT__,YY_VOLATILE,YY___VOLATILE,YY___VOLATILE__,YY__ATOMIC), "\000\000\376\007\000\000\000\000\000\000\000\000\000")) {
sym = parse_type_qualifier(sym, dcl);
} else 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")) {
@@ -2225,7 +2226,7 @@ static int parse_type_qualifier(int sym, zend_ffi_dcl *dcl) {
return sym;
}
-static int parse_type_specifier(int sym, zend_ffi_dcl *dcl) {
+static int parse_type_specifier(int sym, zend_ffi_dcl *dcl, bool standalone_type) {
const char *name;
size_t name_len;
switch (sym) {
@@ -2299,7 +2300,7 @@ static int parse_type_specifier(int sym, zend_ffi_dcl *dcl) {
break;
case YY_ENUM:
if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);
- sym = parse_enum_specifier(sym, dcl);
+ sym = parse_enum_specifier(sym, dcl, standalone_type);
break;
case YY_ID:
if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);
@@ -2459,7 +2460,7 @@ static int parse_struct_declarator(int sym, zend_ffi_dcl *struct_dcl, zend_ffi_d
return sym;
}
-static int parse_enum_specifier(int sym, zend_ffi_dcl *dcl) {
+static int parse_enum_specifier(int sym, zend_ffi_dcl *dcl, bool standalone_type) {
if (sym != YY_ENUM) {
yy_error_sym("'enum' expected, got", sym);
}
@@ -2499,6 +2500,7 @@ static int parse_enum_specifier(int sym, zend_ffi_dcl *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, dcl);
}
+ if (standalone_type) zend_ffi_cleanup_dcl(dcl);
} else {
yy_error_sym("unexpected", 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, ...);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment