Created
March 2, 2012 03:27
-
-
Save ircmaxell/1955338 to your computer and use it in GitHub Desktop.
POC for type casting (same rules as internal variables)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: Zend/zend_execute.c | |
=================================================================== | |
--- Zend/zend_execute.c (revision 322430) | |
+++ Zend/zend_execute.c (working copy) | |
@@ -646,7 +646,39 @@ | |
return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "" TSRMLS_CC); | |
} | |
break; | |
- | |
+ case IS_DOUBLE: | |
+ break; | |
+ case IS_BOOL: | |
+ break; | |
+ case IS_STRING: | |
+ break; | |
+ case IS_OBJECT: | |
+ break; | |
+ case IS_LONG: | |
+ if (!arg) { | |
+ return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type integer", "", "none", "" TSRMLS_CC); | |
+ } | |
+ switch (Z_TYPE_P(arg)) { | |
+ case IS_STRING: | |
+ { | |
+ long *p = NULL; | |
+ double *d = NULL; | |
+ if (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), p, d, -1) == 0) { | |
+ return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type integer", "", zend_zval_type_name(arg), "" TSRMLS_CC); | |
+ } | |
+ } | |
+ /* Fall Through Intentional */ | |
+ case IS_LONG: | |
+ case IS_BOOL: | |
+ case IS_NULL: | |
+ convert_to_long(arg); | |
+ break; | |
+ case IS_OBJECT: | |
+ // TODO: Implement object casting | |
+ default: | |
+ return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type integer", "", zend_zval_type_name(arg), "" TSRMLS_CC); | |
+ } | |
+ break; | |
default: | |
zend_error(E_ERROR, "Unknown typehint"); | |
} | |
Index: Zend/zend_compile.c | |
=================================================================== | |
--- Zend/zend_compile.c (revision 322430) | |
+++ Zend/zend_compile.c (working copy) | |
@@ -1889,6 +1889,52 @@ | |
zend_error(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL"); | |
} | |
} | |
+ } else if (class_type->u.constant.type == IS_LONG) { | |
+ cur_arg_info->type_hint = IS_LONG; | |
+ if (op == ZEND_RECV_INIT) { | |
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { | |
+ cur_arg_info->allow_null = 1; | |
+ } else if (Z_TYPE(initialization->u.constant) != IS_LONG) { | |
+ zend_error(E_COMPILE_ERROR, "Default value for parameters with int type hint can only be INT or NULL"); | |
+ } | |
+ } | |
+ } else if (class_type->u.constant.type == IS_DOUBLE) { | |
+ cur_arg_info->type_hint = IS_DOUBLE; | |
+ if (op == ZEND_RECV_INIT) { | |
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { | |
+ cur_arg_info->allow_null = 1; | |
+ } else if (Z_TYPE(initialization->u.constant) != IS_DOUBLE) { | |
+ zend_error(E_COMPILE_ERROR, "Default value for parameters with float type hint can only be INT or NULL"); | |
+ } | |
+ } | |
+ } else if (class_type->u.constant.type == IS_BOOL) { | |
+ cur_arg_info->type_hint = IS_BOOL; | |
+ if (op == ZEND_RECV_INIT) { | |
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { | |
+ cur_arg_info->allow_null = 1; | |
+ } else if (Z_TYPE(initialization->u.constant) != IS_BOOL) { | |
+ zend_error(E_COMPILE_ERROR, "Default value for parameters with bool type hint can only be INT or NULL"); | |
+ } | |
+ } | |
+ } else if (class_type->u.constant.type == IS_OBJECT) { | |
+ cur_arg_info->type_hint = IS_OBJECT; | |
+ if (op == ZEND_RECV_INIT) { | |
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { | |
+ cur_arg_info->allow_null = 1; | |
+ } else if (Z_TYPE(initialization->u.constant) != IS_OBJECT) { | |
+ zend_error(E_COMPILE_ERROR, "Default value for parameters with object type hint can only be INT or NULL"); | |
+ } | |
+ } | |
+ } else if (class_type->u.constant.type == IS_STRING) { | |
+ cur_arg_info->type_hint = IS_STRING; | |
+ if (op == ZEND_RECV_INIT) { | |
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { | |
+ cur_arg_info->allow_null = 1; | |
+ } else if (Z_TYPE(initialization->u.constant) != IS_STRING) { | |
+ zend_error(E_COMPILE_ERROR, "Default value for parameters with string type hint can only be INT or NULL"); | |
+ } | |
+ } | |
+ | |
} else if (class_type->u.constant.type == IS_CALLABLE) { | |
cur_arg_info->type_hint = IS_CALLABLE; | |
if (op == ZEND_RECV_INIT) { | |
@@ -3089,6 +3135,17 @@ | |
} else if (arg_info->type_hint) { | |
zend_uint type_name_len; | |
char *type_name = zend_get_type_by_const(arg_info->type_hint); | |
+ switch (arg_info->type_hint) { | |
+ case IS_OBJECT: | |
+ if (arg_info->class_name) { | |
+ break; | |
+ } | |
+ case IS_LONG: | |
+ case IS_DOUBLE: | |
+ case IS_BOOL: | |
+ case IS_STRING: | |
+ type_name = sprintf("(%s)", type_name); | |
+ } | |
type_name_len = strlen(type_name); | |
REALLOC_BUF_IF_EXCEED(buf, offset, length, type_name_len); | |
memcpy(offset, type_name, type_name_len); | |
Index: Zend/zend_language_parser.y | |
=================================================================== | |
--- Zend/zend_language_parser.y (revision 322430) | |
+++ Zend/zend_language_parser.y (working copy) | |
@@ -508,7 +508,6 @@ | |
| /* empty */ | |
; | |
- | |
non_empty_parameter_list: | |
optional_class_type T_VARIABLE { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV, &$2, &$$, NULL, &$1, 0 TSRMLS_CC); } | |
| optional_class_type '&' T_VARIABLE { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV, &$3, &$$, NULL, &$1, 1 TSRMLS_CC); } | |
@@ -525,6 +524,11 @@ | |
/* empty */ { $$.op_type = IS_UNUSED; } | |
| T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_ARRAY; } | |
| T_CALLABLE { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_CALLABLE; } | |
+ | T_BOOL_CAST { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_BOOL; } | |
+ | T_INT_CAST { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_LONG; } | |
+ | T_DOUBLE_CAST { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_DOUBLE; } | |
+ | T_STRING_CAST { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_STRING; } | |
+ | T_OBJECT_CAST { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_OBJECT; } | |
| fully_qualified_class_name { $$ = $1; } | |
; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment