]> granicus.if.org Git - php/commitdiff
Fixed bug #77768 (FFI: Builtin Types Should Not Raise Error On Redeclaration)
authorDmitry Stogov <dmitry@zend.com>
Thu, 28 Mar 2019 21:02:26 +0000 (00:02 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 28 Mar 2019 21:02:26 +0000 (00:02 +0300)
ext/ffi/ffi.c
ext/ffi/tests/bug77768.phpt [new file with mode: 0644]

index ba15151dd5d4cb6389d9575a48954ea34a079a83..e8061a46825ae7d5a3a4316d1e9d935ca7a12c41 100644 (file)
@@ -5772,11 +5772,39 @@ void zend_ffi_declare(const char *name, size_t name_len, zend_ffi_dcl *dcl) /* {
                FFI_G(symbols) = pemalloc(sizeof(HashTable), FFI_G(persistent));
                zend_hash_init(FFI_G(symbols), 0, NULL, FFI_G(persistent) ? zend_ffi_symbol_hash_persistent_dtor : zend_ffi_symbol_hash_dtor, FFI_G(persistent));
        }
+       zend_ffi_finalize_type(dcl);
        sym = zend_hash_str_find_ptr(FFI_G(symbols), name, name_len);
        if (sym) {
+               if ((dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) == ZEND_FFI_DCL_TYPEDEF
+                && sym->kind == ZEND_FFI_SYM_TYPE
+                && zend_ffi_is_same_type(ZEND_FFI_TYPE(sym->type), ZEND_FFI_TYPE(dcl->type))
+                && sym->is_const == (zend_bool)(dcl->attr & ZEND_FFI_ATTR_CONST)) {
+                       /* allowed redeclaration */
+                       zend_ffi_type_dtor(dcl->type);
+                       return;
+               } else if ((dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) == 0
+                || (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) == ZEND_FFI_DCL_EXTERN) {
+                       zend_ffi_type *type = ZEND_FFI_TYPE(dcl->type);
+
+                       if (type->kind == ZEND_FFI_TYPE_FUNC) {
+                               if (sym->kind == ZEND_FFI_SYM_FUNC
+                                && zend_ffi_same_types(ZEND_FFI_TYPE(sym->type), type)) {
+                                       /* allowed redeclaration */
+                                       zend_ffi_type_dtor(dcl->type);
+                                       return;
+                               }
+                       } else {
+                               if (sym->kind == ZEND_FFI_SYM_VAR
+                                && zend_ffi_is_same_type(ZEND_FFI_TYPE(sym->type), type)
+                                && sym->is_const == (zend_bool)(dcl->attr & ZEND_FFI_ATTR_CONST)) {
+                                       /* allowed redeclaration */
+                                       zend_ffi_type_dtor(dcl->type);
+                                       return;
+                               }
+                       }
+               }
                zend_ffi_parser_error("redeclaration of '%.*s' at line %d", name_len, name, FFI_G(line));
        } else {
-               zend_ffi_finalize_type(dcl);
                if ((dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) == ZEND_FFI_DCL_TYPEDEF) {
                        if (zend_ffi_validate_vla(ZEND_FFI_TYPE(dcl->type)) != SUCCESS) {
                                zend_ffi_cleanup_dcl(dcl);
diff --git a/ext/ffi/tests/bug77768.phpt b/ext/ffi/tests/bug77768.phpt
new file mode 100644 (file)
index 0000000..6c29db5
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+Bug #77768 (Redeclaration of builtin types and repeated declarations)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+try {
+       $libc = FFI::cdef("int printf(const char *format, ...);", "libc.so.6");
+} catch (Throwable $_) {
+       die('skip libc.so.6 not available');
+}
+?>
+--INI--
+ffi.enable=1
+--FILE--
+<?php
+$x = FFI::cdef("
+typedef __builtin_va_list __gnuc_va_list;
+typedef unsigned int uint8_t;
+
+typedef int64_t a;
+typedef int64_t b;
+typedef a c;
+typedef b c;
+
+struct point {int x,y;};
+
+typedef struct point d;
+typedef struct point d;
+
+int printf(const char *format, ...);
+int printf(const char *format, ...);
+");
+
+var_dump(FFI::sizeof($x->new("uint8_t")));
+var_dump(FFI::sizeof(FFI::new("uint8_t")));
+?>
+--EXPECT--
+int(4)
+int(1)