Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial support for enforcing prototype of abstract/interface method …

…implementations
  • Loading branch information...
commit 5097be302ec961bd9305244a89b4a5f9ddb2ab50 1 parent 9e6fdcd
@zsuraski zsuraski authored
Showing with 75 additions and 12 deletions.
  1. +1 −0  Zend/zend_API.c
  2. +57 −0 Zend/zend_compile.c
  3. +17 −12 Zend/zend_compile.h
View
1  Zend/zend_API.c
@@ -1166,6 +1166,7 @@ int zend_register_functions(zend_class_entry *scope, zend_function_entry *functi
internal_function->scope = scope;
internal_function->fn_flags = ZEND_ACC_PUBLIC;
internal_function->ns = EG(active_namespace);
+ internal_function->prototype = NULL;
if (!internal_function->handler) {
zend_error(error_type, "Null function defined as active function");
zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
View
57 Zend/zend_compile.c
@@ -1630,6 +1630,53 @@ static void do_inherit_method(zend_function *function)
}
+static zend_bool zend_do_perform_implementation_check(zend_function *fe)
+{
+ zend_op *op, *proto_op;
+
+ if (!fe->common.prototype) {
+ return 1;
+ }
+
+ if ((fe->common.arg_types && !fe->common.prototype->common.arg_types)
+ || (!fe->common.arg_types && fe->common.prototype->common.arg_types)) {
+ return 0;
+ }
+
+ if (fe->common.arg_types) {
+ if (fe->common.arg_types[0] != fe->common.prototype->common.arg_types[0]) {
+ return 0;
+ }
+ if (memcmp(fe->common.arg_types+1, fe->common.prototype->common.arg_types+1, fe->common.arg_types[0]*sizeof(zend_uchar)) != 0) {
+ return 0;
+ }
+ }
+
+ if (fe->common.prototype->type == ZEND_INTERNAL_FUNCTION) {
+ return 1; /* nothing further we can do here */
+ }
+
+ op = fe->op_array.opcodes;
+ proto_op = fe->common.prototype->op_array.opcodes;
+
+ while (proto_op->opcode != ZEND_RAISE_ABSTRACT_ERROR) {
+ if (proto_op->opcode != op->opcode) {
+ return 0;
+ }
+ switch (proto_op->opcode) {
+ case ZEND_FETCH_CLASS:
+ if (zend_binary_zval_strcasecmp(&op->op2.u.constant, &proto_op->op2.u.constant)!=0) {
+ return 0;
+ }
+ break;
+ }
+ proto_op++;
+ op++;
+ }
+ return 1;
+}
+
+
static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, zend_hash_key *hash_key, zend_class_entry *child_ce)
{
zend_uint child_flags;
@@ -1676,6 +1723,16 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
}
}
+ if (parent_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_ABSTRACT)) {
+ child->common.prototype = parent;
+ } else if (parent->common.prototype) {
+ child->common.prototype = parent->common.prototype;
+ }
+
+ if (!zend_do_perform_implementation_check(child)) {
+ zend_error(E_COMPILE_ERROR, "Declaration of %s::%s() must be the same as %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
+ }
+
return 0;
}
View
29 Zend/zend_compile.h
@@ -116,13 +116,15 @@ typedef struct _zend_property_info {
struct _zend_op_array {
- zend_uchar type; /* MUST be the first element of this struct! */
-
- zend_uchar *arg_types; /* MUST be the second element of this struct! */
- char *function_name; /* MUST be the third element of this struct! */
- zend_class_entry *scope; /* MUST be the fourth element of this struct! */
- zend_uint fn_flags; /* MUST be the fifth element of this struct! */
+ /* Common elements */
+ zend_uchar type;
+ zend_uchar *arg_types;
+ char *function_name;
+ zend_class_entry *scope;
+ zend_uint fn_flags;
zend_namespace *ns;
+ union _zend_function *prototype;
+ /* END of common elements */
zend_uint *refcount;
@@ -154,13 +156,15 @@ struct _zend_op_array {
typedef struct _zend_internal_function {
- zend_uchar type; /* MUST be the first element of this struct! */
-
- zend_uchar *arg_types; /* MUST be the second element of this struct! */
- char *function_name; /* MUST be the third element of this struct! */
- zend_class_entry *scope; /* MUST be the fourth element of this struct! */
- zend_uint fn_flags; /* MUST be the fifth element of this struct! */
+ /* Common elements */
+ zend_uchar type;
+ zend_uchar *arg_types;
+ char *function_name;
+ zend_class_entry *scope;
+ zend_uint fn_flags;
zend_namespace *ns;
+ union _zend_function *prototype;
+ /* END of common elements */
void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
} zend_internal_function;
@@ -177,6 +181,7 @@ typedef union _zend_function {
zend_class_entry *scope;
zend_uint fn_flags;
zend_namespace *ns;
+ union _zend_function *prototype;
} common;
zend_op_array op_array;
Please sign in to comment.
Something went wrong with that request. Please try again.