summaryrefslogtreecommitdiff
path: root/ext/reflection/php_reflection.c
diff options
context:
space:
mode:
authorXinchen Hui <laruence@gmail.com>2017-07-27 11:23:27 +0800
committerXinchen Hui <laruence@gmail.com>2017-07-27 11:23:27 +0800
commit84a18c47824d126b914bbddc85ed785699fe1544 (patch)
tree37a64a4701bdda61f381538a4ac06176886270e5 /ext/reflection/php_reflection.c
parent80f4297c25ca3e1f2378e00d6a54d148c62de530 (diff)
parente36c04ef483d85fe145ee07280d8c31e7e295644 (diff)
downloadphp-git-84a18c47824d126b914bbddc85ed785699fe1544.tar.gz
Merge branch 'PHP-7.0' into PHP-7.1
* PHP-7.0: Fixed bug #74949 (null pointer dereference in _function_string)
Diffstat (limited to 'ext/reflection/php_reflection.c')
-rw-r--r--ext/reflection/php_reflection.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index db7056e03b..fa936d2e15 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -295,6 +295,15 @@ static zend_function *_copy_function(zend_function *fptr) /* {{{ */
}
/* }}} */
+static void _fix_closure_prototype(zend_function *fptr) /* {{{ */
+{
+ /* Actually we are setting proxy function's prototype to null
+ * as for it, the prototype is an object not a function
+ * which could cause serias problems, see #74949 */
+ fptr->common.prototype = NULL;
+}
+/* }}} */
+
static void _free_function(zend_function *fptr) /* {{{ */
{
if (fptr
@@ -603,6 +612,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
&& memcmp(ZSTR_VAL(mptr->common.function_name), ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
&& (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
{
+ _fix_closure_prototype(closure);
mptr = closure;
} else {
closure = NULL;
@@ -2364,7 +2374,6 @@ ZEND_METHOD(reflection_generator, getExecutingGenerator)
}
/* }}} */
-
/* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter [, bool return]) throws ReflectionException
Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_parameter, export)
@@ -2449,6 +2458,7 @@ ZEND_METHOD(reflection_parameter, __construct)
{
/* nothing to do. don't set is_closure since is the invoke handler,
not the closure itself */
+ _fix_closure_prototype(fptr);
} else if ((fptr = zend_hash_str_find_ptr(&ce->function_table, lcname, lcname_len)) == NULL) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0,
@@ -3152,6 +3162,7 @@ ZEND_METHOD(reflection_method, __construct)
&& (mptr = zend_get_closure_invoke_method(Z_OBJ_P(orig_obj))) != NULL)
{
/* do nothing, mptr already set */
+ _fix_closure_prototype(mptr);
} else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, name_len)) == NULL) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0,
@@ -4278,6 +4289,7 @@ ZEND_METHOD(reflection_class, getMethod)
{
/* don't assign closure_object since we only reflect the invoke handler
method and not the closure definition itself */
+ _fix_closure_prototype(mptr);
reflection_method_factory(ce, mptr, NULL, return_value);
efree(lc_name);
} else if (ce == zend_ce_closure && Z_ISUNDEF(intern->obj) && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
@@ -4285,6 +4297,7 @@ ZEND_METHOD(reflection_class, getMethod)
&& object_init_ex(&obj_tmp, ce) == SUCCESS && (mptr = zend_get_closure_invoke_method(Z_OBJ(obj_tmp))) != NULL) {
/* don't assign closure_object since we only reflect the invoke handler
method and not the closure definition itself */
+ _fix_closure_prototype(mptr);
reflection_method_factory(ce, mptr, NULL, return_value);
zval_dtor(&obj_tmp);
efree(lc_name);
@@ -4311,6 +4324,7 @@ static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval,
&& memcmp(ZSTR_VAL(mptr->common.function_name), ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
&& (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
{
+ _fix_closure_prototype(closure);
mptr = closure;
}
/* don't assign closure_object since we only reflect the invoke handler
@@ -4362,6 +4376,7 @@ ZEND_METHOD(reflection_class, getMethods)
if (Z_TYPE(intern->obj) != IS_UNDEF && instanceof_function(ce, zend_ce_closure)) {
zend_function *closure = zend_get_closure_invoke_method(Z_OBJ(intern->obj));
if (closure) {
+ _fix_closure_prototype(closure);
_addmethod(closure, ce, return_value, filter, &intern->obj);
_free_function(closure);
}