2006-05-09 23:53:23 +00:00
/*
2003-02-01 01:49:15 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Zend Engine |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2016-01-02 09:56:11 +00:00
| Copyright ( c ) 1998 - 2016 Zend Technologies Ltd . ( http : //www.zend.com) |
2003-02-01 01:49:15 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| This source file is subject to version 2.00 of the Zend license , |
| that is bundled with this package in the file LICENSE , and is |
2003-06-10 20:04:29 +00:00
| available through the world - wide - web at the following url : |
2003-02-01 01:49:15 +00:00
| http : //www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ zend . com so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Andi Gutmans < andi @ zend . com > |
| Zeev Suraski < zeev @ zend . com > |
2015-08-31 08:38:16 +00:00
| Dmitry Stogov < dmitry @ zend . com > |
2003-02-01 01:49:15 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
2002-02-07 14:08:43 +00:00
# include "zend.h"
# include "zend_globals.h"
# include "zend_variables.h"
# include "zend_API.h"
# include "zend_objects.h"
2002-05-31 12:09:19 +00:00
# include "zend_objects_API.h"
2002-02-07 14:08:43 +00:00
# include "zend_object_handlers.h"
2003-11-24 20:57:54 +00:00
# include "zend_interfaces.h"
2015-07-03 18:41:17 +00:00
# include "zend_exceptions.h"
2008-08-14 21:36:56 +00:00
# include "zend_closures.h"
2009-06-18 13:46:16 +00:00
# include "zend_compile.h"
2013-12-12 19:25:10 +00:00
# include "zend_hash.h"
2002-02-07 14:08:43 +00:00
2002-02-21 11:50:44 +00:00
# define DEBUG_OBJECT_HANDLERS 0
2002-02-07 14:08:43 +00:00
2014-02-10 06:04:30 +00:00
/* guard flags */
# define IN_GET (1<<0)
# define IN_SET (1<<1)
# define IN_UNSET (1<<2)
# define IN_ISSET (1<<3)
2003-01-12 14:39:45 +00:00
2013-01-09 07:30:50 +00:00
# define Z_OBJ_PROTECT_RECURSION(zval_p) \
do { \
2014-02-12 14:08:11 +00:00
if ( Z_OBJ_APPLY_COUNT_P ( zval_p ) > = 3 ) { \
2015-04-01 10:32:23 +00:00
zend_error_noreturn ( E_ERROR , " Nesting level too deep - recursive dependency? " ) ; \
2013-01-09 07:30:50 +00:00
} \
2014-02-12 14:08:11 +00:00
Z_OBJ_INC_APPLY_COUNT_P ( zval_p ) ; \
2013-01-09 07:30:50 +00:00
} while ( 0 )
# define Z_OBJ_UNPROTECT_RECURSION(zval_p) \
2014-02-12 14:08:11 +00:00
Z_OBJ_DEC_APPLY_COUNT_P ( zval_p )
2013-01-09 07:30:50 +00:00
2002-09-04 09:07:58 +00:00
/*
__X accessors explanation :
if we have __get and property that is not part of the properties array is
requested , we call __get handler . If it fails , we return uninitialized .
if we have __set and property that is not part of the properties array is
set , we call __set handler . If it fails , we do not change the array .
for both handlers above , when we are inside __get / __set , no further calls for
2007-10-11 01:03:19 +00:00
__get / __set for this property of this object will be made , to prevent endless
2007-03-23 17:16:55 +00:00
recursion and enable accessors to change properties array .
2002-09-04 09:07:58 +00:00
if we have __call and method which is not part of the class function table is
2006-05-09 23:53:23 +00:00
called , we cal __call handler .
2002-09-04 09:07:58 +00:00
*/
2010-05-24 14:11:39 +00:00
ZEND_API void rebuild_object_properties ( zend_object * zobj ) /* { { { */
{
if ( ! zobj - > properties ) {
zend_property_info * prop_info ;
zend_class_entry * ce = zobj - > ce ;
ALLOC_HASHTABLE ( zobj - > properties ) ;
2014-07-08 09:46:03 +00:00
zend_hash_init ( zobj - > properties , ce - > default_properties_count , NULL , ZVAL_PTR_DTOR , 0 ) ;
2010-05-24 14:11:39 +00:00
if ( ce - > default_properties_count ) {
2015-03-06 16:23:54 +00:00
zend_hash_real_init ( zobj - > properties , 0 ) ;
zobj - > properties - > nInternalPointer = 0 ;
2014-04-18 15:18:11 +00:00
ZEND_HASH_FOREACH_PTR ( & ce - > properties_info , prop_info ) {
2010-05-24 14:11:39 +00:00
if ( /*prop_info->ce == ce &&*/
2015-08-26 00:27:05 +00:00
( prop_info - > flags & ZEND_ACC_STATIC ) = = 0 ) {
if ( UNEXPECTED ( Z_TYPE_P ( OBJ_PROP ( zobj , prop_info - > offset ) ) = = IS_UNDEF ) ) {
zobj - > properties - > u . v . flags | = HASH_FLAG_HAS_EMPTY_IND ;
}
2014-03-26 14:07:31 +00:00
2015-03-06 16:23:54 +00:00
_zend_hash_append_ind ( zobj - > properties , prop_info - > name ,
OBJ_PROP ( zobj , prop_info - > offset ) ) ;
2012-05-13 05:12:48 +00:00
}
2014-04-18 15:18:11 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2010-05-24 14:11:39 +00:00
while ( ce - > parent & & ce - > parent - > default_properties_count ) {
ce = ce - > parent ;
2014-04-18 15:18:11 +00:00
ZEND_HASH_FOREACH_PTR ( & ce - > properties_info , prop_info ) {
2010-05-24 14:11:39 +00:00
if ( prop_info - > ce = = ce & &
2012-05-13 05:12:48 +00:00
( prop_info - > flags & ZEND_ACC_STATIC ) = = 0 & &
2015-08-26 00:27:05 +00:00
( prop_info - > flags & ZEND_ACC_PRIVATE ) ! = 0 ) {
2014-03-26 14:07:31 +00:00
zval zv ;
2015-01-03 09:22:58 +00:00
2015-08-26 00:27:05 +00:00
if ( UNEXPECTED ( Z_TYPE_P ( OBJ_PROP ( zobj , prop_info - > offset ) ) = = IS_UNDEF ) ) {
zobj - > properties - > u . v . flags | = HASH_FLAG_HAS_EMPTY_IND ;
}
2014-11-06 11:50:03 +00:00
ZVAL_INDIRECT ( & zv , OBJ_PROP ( zobj , prop_info - > offset ) ) ;
2014-03-26 14:07:31 +00:00
zend_hash_add ( zobj - > properties , prop_info - > name , & zv ) ;
2012-05-13 05:12:48 +00:00
}
2014-04-18 15:18:11 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2010-05-24 14:11:39 +00:00
}
}
}
}
2011-09-15 14:50:38 +00:00
/* }}} */
2010-05-24 14:11:39 +00:00
2014-12-13 22:06:14 +00:00
ZEND_API HashTable * zend_std_get_properties ( zval * object ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2010-05-24 14:11:39 +00:00
if ( ! zobj - > properties ) {
rebuild_object_properties ( zobj ) ;
}
2002-02-07 14:08:43 +00:00
return zobj - > properties ;
}
2007-11-02 19:40:39 +00:00
/* }}} */
2014-12-13 22:06:14 +00:00
ZEND_API HashTable * zend_std_get_gc ( zval * object , zval * * table , int * n ) /* { { { */
2011-11-02 06:31:33 +00:00
{
if ( Z_OBJ_HANDLER_P ( object , get_properties ) ! = zend_std_get_properties ) {
* table = NULL ;
* n = 0 ;
2014-12-13 22:06:14 +00:00
return Z_OBJ_HANDLER_P ( object , get_properties ) ( object ) ;
2011-11-02 06:31:33 +00:00
} else {
zend_object * zobj = Z_OBJ_P ( object ) ;
2015-05-06 18:33:49 +00:00
if ( zobj - > properties ) {
* table = NULL ;
* n = 0 ;
return zobj - > properties ;
} else {
* table = zobj - > properties_table ;
* n = zobj - > ce - > default_properties_count ;
return NULL ;
}
2011-11-02 06:31:33 +00:00
}
}
/* }}} */
2014-12-13 22:06:14 +00:00
ZEND_API HashTable * zend_std_get_debug_info ( zval * object , int * is_temp ) /* { { { */
2007-11-02 19:40:39 +00:00
{
2014-02-18 03:13:00 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2014-04-25 20:32:51 +00:00
zval retval ;
HashTable * ht ;
2014-02-18 03:13:00 +00:00
if ( ! ce - > __debugInfo ) {
* is_temp = 0 ;
return Z_OBJ_HANDLER_P ( object , get_properties )
2014-12-13 22:06:14 +00:00
? Z_OBJ_HANDLER_P ( object , get_properties ) ( object )
2014-02-18 03:13:00 +00:00
: NULL ;
}
2014-04-25 20:32:51 +00:00
zend_call_method_with_0_params ( object , ce , & ce - > __debugInfo , ZEND_DEBUGINFO_FUNC_NAME , & retval ) ;
if ( Z_TYPE ( retval ) = = IS_ARRAY ) {
2014-06-02 22:43:53 +00:00
if ( Z_IMMUTABLE ( retval ) ) {
* is_temp = 1 ;
2015-02-13 19:20:39 +00:00
return zend_array_dup ( Z_ARRVAL ( retval ) ) ;
2014-06-02 22:43:53 +00:00
} else if ( Z_REFCOUNT ( retval ) < = 1 ) {
2014-02-18 03:13:00 +00:00
* is_temp = 1 ;
2015-09-14 20:04:27 +00:00
ht = Z_ARR ( retval ) ;
2014-02-18 03:13:00 +00:00
return ht ;
} else {
* is_temp = 0 ;
zval_ptr_dtor ( & retval ) ;
2014-06-02 22:43:53 +00:00
return Z_ARRVAL ( retval ) ;
2014-02-18 03:13:00 +00:00
}
2014-04-25 20:32:51 +00:00
} else if ( Z_TYPE ( retval ) = = IS_NULL ) {
2014-02-18 03:13:00 +00:00
* is_temp = 1 ;
2014-04-25 20:32:51 +00:00
ALLOC_HASHTABLE ( ht ) ;
zend_hash_init ( ht , 0 , NULL , ZVAL_PTR_DTOR , 0 ) ;
return ht ;
2014-02-18 03:13:00 +00:00
}
2015-04-01 10:32:23 +00:00
zend_error_noreturn ( E_ERROR , ZEND_DEBUGINFO_FUNC_NAME " () must return an array " ) ;
2014-04-11 17:33:56 +00:00
return NULL ; /* Compilers are dumb and don't understand that noreturn means that the function does NOT need a return value... */
2007-11-02 19:40:39 +00:00
}
/* }}} */
2002-02-07 14:08:43 +00:00
2014-12-13 22:06:14 +00:00
static void zend_std_call_getter ( zval * object , zval * member , zval * retval ) /* { { { */
2002-09-04 09:07:58 +00:00
{
2004-09-28 22:55:22 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2006-05-09 23:53:23 +00:00
2004-09-28 22:55:22 +00:00
/* __get handler is called with one argument:
property name
2002-09-04 09:07:58 +00:00
2014-11-19 19:59:31 +00:00
it should return whether the call was successful or not
2002-09-04 09:07:58 +00:00
*/
2014-06-05 12:04:11 +00:00
if ( Z_REFCOUNTED_P ( member ) ) Z_ADDREF_P ( member ) ;
2005-02-02 07:19:22 +00:00
2014-02-10 06:04:30 +00:00
zend_call_method_with_1_params ( object , ce , & ce - > __get , ZEND_GET_FUNC_NAME , retval , member ) ;
2002-09-04 09:07:58 +00:00
2014-02-10 06:04:30 +00:00
zval_ptr_dtor ( member ) ;
2002-09-04 09:07:58 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-09-04 09:07:58 +00:00
2014-12-13 22:06:14 +00:00
static int zend_std_call_setter ( zval * object , zval * member , zval * value ) /* { { { */
2002-09-04 09:07:58 +00:00
{
2014-02-10 06:04:30 +00:00
zval retval ;
2005-03-19 15:32:18 +00:00
int result ;
2004-09-28 22:55:22 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2005-02-02 07:19:22 +00:00
2014-06-05 12:04:11 +00:00
if ( Z_REFCOUNTED_P ( member ) ) Z_ADDREF_P ( member ) ;
2014-02-21 16:35:40 +00:00
if ( Z_REFCOUNTED_P ( value ) ) Z_ADDREF_P ( value ) ;
2004-09-28 22:55:22 +00:00
2002-09-04 09:07:58 +00:00
/* __set handler is called with two arguments:
2004-09-28 22:55:22 +00:00
property name
value to be set
2002-09-04 09:07:58 +00:00
2014-11-19 19:59:31 +00:00
it should return whether the call was successful or not
2002-09-04 09:07:58 +00:00
*/
2014-02-10 06:04:30 +00:00
zend_call_method_with_2_params ( object , ce , & ce - > __set , ZEND_SET_FUNC_NAME , & retval , member , value ) ;
2002-09-04 09:07:58 +00:00
2014-02-10 06:04:30 +00:00
zval_ptr_dtor ( member ) ;
zval_ptr_dtor ( value ) ;
2002-09-04 09:07:58 +00:00
2014-02-10 06:04:30 +00:00
if ( Z_TYPE ( retval ) ! = IS_UNDEF ) {
2014-12-13 22:06:14 +00:00
result = i_zend_is_true ( & retval ) ? SUCCESS : FAILURE ;
2002-09-04 09:07:58 +00:00
zval_ptr_dtor ( & retval ) ;
2005-03-19 15:32:18 +00:00
return result ;
} else {
return FAILURE ;
2002-09-04 09:07:58 +00:00
}
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-09-04 09:07:58 +00:00
2014-12-13 22:06:14 +00:00
static void zend_std_call_unsetter ( zval * object , zval * member ) /* { { { */
2005-07-07 16:07:09 +00:00
{
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2006-05-09 23:53:23 +00:00
2005-07-07 16:07:09 +00:00
/* __unset handler is called with one argument:
property name
*/
2006-05-09 23:53:23 +00:00
2014-06-05 12:04:11 +00:00
if ( Z_REFCOUNTED_P ( member ) ) Z_ADDREF_P ( member ) ;
2005-07-07 16:07:09 +00:00
2014-02-10 06:04:30 +00:00
zend_call_method_with_1_params ( object , ce , & ce - > __unset , ZEND_UNSET_FUNC_NAME , NULL , member ) ;
2005-07-07 16:07:09 +00:00
2014-02-10 06:04:30 +00:00
zval_ptr_dtor ( member ) ;
2005-07-07 16:07:09 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2005-07-07 16:07:09 +00:00
2014-12-13 22:06:14 +00:00
static void zend_std_call_issetter ( zval * object , zval * member , zval * retval ) /* { { { */
2005-07-07 16:07:09 +00:00
{
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2006-05-09 23:53:23 +00:00
2005-07-07 16:07:09 +00:00
/* __isset handler is called with one argument:
property name
it should return whether the property is set or not
*/
2006-05-09 23:53:23 +00:00
2014-06-05 12:04:11 +00:00
if ( Z_REFCOUNTED_P ( member ) ) Z_ADDREF_P ( member ) ;
2005-07-07 16:07:09 +00:00
2014-02-10 06:04:30 +00:00
zend_call_method_with_1_params ( object , ce , & ce - > __isset , ZEND_ISSET_FUNC_NAME , retval , member ) ;
2005-07-07 16:07:09 +00:00
2014-02-10 06:04:30 +00:00
zval_ptr_dtor ( member ) ;
2005-07-07 16:07:09 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-02-04 12:12:34 +00:00
2014-12-13 22:06:14 +00:00
static zend_always_inline int zend_verify_property_access ( zend_property_info * property_info , zend_class_entry * ce ) /* { { { */
2003-02-04 12:12:34 +00:00
{
2015-06-03 10:43:05 +00:00
if ( property_info - > flags & ZEND_ACC_PUBLIC ) {
return 1 ;
} else if ( property_info - > flags & ZEND_ACC_PRIVATE ) {
return ( ce = = EG ( scope ) | | property_info - > ce = = EG ( scope ) ) ;
2015-11-07 14:50:24 +00:00
} else if ( property_info - > flags & ZEND_ACC_PROTECTED ) {
2015-06-03 10:43:05 +00:00
return zend_check_protected ( property_info - > ce , EG ( scope ) ) ;
2003-02-04 12:12:34 +00:00
}
2015-11-07 14:50:24 +00:00
return 0 ;
2003-02-04 12:12:34 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-02-04 12:12:34 +00:00
2010-05-24 14:11:39 +00:00
static zend_always_inline zend_bool is_derived_class ( zend_class_entry * child_class , zend_class_entry * parent_class ) /* { { { */
2003-07-21 12:13:16 +00:00
{
child_class = child_class - > parent ;
while ( child_class ) {
if ( child_class = = parent_class ) {
return 1 ;
}
child_class = child_class - > parent ;
}
return 0 ;
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-07-21 12:13:16 +00:00
2015-01-13 08:33:00 +00:00
static zend_always_inline uint32_t zend_get_property_offset ( zend_class_entry * ce , zend_string * member , int silent , void * * cache_slot ) /* { { { */
2003-02-07 10:05:36 +00:00
{
2014-10-20 16:33:35 +00:00
zval * zv ;
zend_property_info * property_info = NULL ;
uint32_t flags ;
2003-03-18 16:30:23 +00:00
2014-07-07 16:54:31 +00:00
if ( cache_slot & & EXPECTED ( ce = = CACHED_PTR_EX ( cache_slot ) ) ) {
2015-01-13 08:33:00 +00:00
return ( uint32_t ) ( intptr_t ) CACHED_PTR_EX ( cache_slot + 1 ) ;
2010-05-24 14:11:39 +00:00
}
2015-06-30 10:59:27 +00:00
if ( UNEXPECTED ( ZSTR_VAL ( member ) [ 0 ] = = ' \0 ' ) ) {
2005-04-28 17:40:11 +00:00
if ( ! silent ) {
2015-06-30 10:59:27 +00:00
if ( ZSTR_LEN ( member ) = = 0 ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access empty property " ) ;
2005-04-28 17:40:11 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access property started with ' \\ 0' " ) ;
2005-04-28 17:40:11 +00:00
}
}
2015-01-13 08:33:00 +00:00
return ZEND_WRONG_PROPERTY_OFFSET ;
2005-04-28 17:40:11 +00:00
}
2014-10-20 16:33:35 +00:00
if ( UNEXPECTED ( zend_hash_num_elements ( & ce - > properties_info ) = = 0 ) ) {
goto exit_dynamic ;
}
zv = zend_hash_find ( & ce - > properties_info , member ) ;
if ( EXPECTED ( zv ! = NULL ) ) {
property_info = ( zend_property_info * ) Z_PTR_P ( zv ) ;
flags = property_info - > flags ;
if ( UNEXPECTED ( ( flags & ZEND_ACC_SHADOW ) ! = 0 ) ) {
2005-06-09 17:20:44 +00:00
/* if it's a shadow - go to access it's private */
property_info = NULL ;
} else {
2014-12-13 22:06:14 +00:00
if ( EXPECTED ( zend_verify_property_access ( property_info , ce ) ! = 0 ) ) {
2014-10-20 16:33:35 +00:00
if ( UNEXPECTED ( ! ( flags & ZEND_ACC_CHANGED ) )
| | UNEXPECTED ( ( flags & ZEND_ACC_PRIVATE ) ) ) {
2014-11-06 11:50:03 +00:00
if ( UNEXPECTED ( ( flags & ZEND_ACC_STATIC ) ! = 0 ) ) {
if ( ! silent ) {
2015-06-30 10:59:27 +00:00
zend_error ( E_NOTICE , " Accessing static property %s::$%s as non static " , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( member ) ) ;
2014-11-06 11:50:03 +00:00
}
2015-01-13 08:33:00 +00:00
return ZEND_DYNAMIC_PROPERTY_OFFSET ;
2005-06-09 17:20:44 +00:00
}
2014-10-20 16:33:35 +00:00
goto exit ;
2005-06-08 08:08:18 +00:00
}
2005-06-09 17:20:44 +00:00
} else {
/* Try to look in the scope instead */
2014-10-20 16:33:35 +00:00
property_info = ZEND_WRONG_PROPERTY_INFO ;
2003-03-18 16:30:23 +00:00
}
2003-02-07 10:05:36 +00:00
}
2003-02-13 22:47:25 +00:00
}
2015-01-03 09:22:58 +00:00
2005-04-08 11:35:11 +00:00
if ( EG ( scope ) ! = ce
2003-03-18 16:30:23 +00:00
& & EG ( scope )
2010-05-24 14:11:39 +00:00
& & is_derived_class ( ce , EG ( scope ) )
2014-10-20 16:33:35 +00:00
& & ( zv = zend_hash_find ( & EG ( scope ) - > properties_info , member ) ) ! = NULL
& & ( ( zend_property_info * ) Z_PTR_P ( zv ) ) - > flags & ZEND_ACC_PRIVATE ) {
property_info = ( zend_property_info * ) Z_PTR_P ( zv ) ;
2015-01-13 08:33:00 +00:00
if ( UNEXPECTED ( ( property_info - > flags & ZEND_ACC_STATIC ) ! = 0 ) ) {
return ZEND_DYNAMIC_PROPERTY_OFFSET ;
2014-11-06 11:50:03 +00:00
}
2014-10-20 16:33:35 +00:00
} else if ( UNEXPECTED ( property_info = = NULL ) ) {
exit_dynamic :
2014-07-07 16:54:31 +00:00
if ( cache_slot ) {
2015-01-13 08:33:00 +00:00
CACHE_POLYMORPHIC_PTR_EX ( cache_slot , ce , ( void * ) ( intptr_t ) ZEND_DYNAMIC_PROPERTY_OFFSET ) ;
2010-05-24 14:11:39 +00:00
}
2015-01-13 08:33:00 +00:00
return ZEND_DYNAMIC_PROPERTY_OFFSET ;
2014-10-20 16:33:35 +00:00
} else if ( UNEXPECTED ( property_info = = ZEND_WRONG_PROPERTY_INFO ) ) {
/* Information was available, but we were denied access. Error out. */
if ( ! silent ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access %s property %s::$%s " , zend_visibility_string ( flags ) , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( member ) ) ;
2003-03-18 16:30:23 +00:00
}
2015-01-13 08:33:00 +00:00
return ZEND_WRONG_PROPERTY_OFFSET ;
2014-10-20 16:33:35 +00:00
}
exit :
if ( cache_slot ) {
2015-01-13 08:33:00 +00:00
CACHE_POLYMORPHIC_PTR_EX ( cache_slot , ce , ( void * ) ( intptr_t ) property_info - > offset ) ;
2003-02-07 10:05:36 +00:00
}
2015-01-13 08:33:00 +00:00
return property_info - > offset ;
2003-02-07 10:05:36 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-02-07 10:05:36 +00:00
2014-12-13 22:06:14 +00:00
ZEND_API zend_property_info * zend_get_property_info ( zend_class_entry * ce , zend_string * member , int silent ) /* { { { */
2010-04-20 10:57:45 +00:00
{
2015-01-13 08:33:00 +00:00
zval * zv ;
zend_property_info * property_info = NULL ;
uint32_t flags ;
2015-06-30 10:59:27 +00:00
if ( UNEXPECTED ( ZSTR_VAL ( member ) [ 0 ] = = ' \0 ' ) ) {
2015-01-13 08:33:00 +00:00
if ( ! silent ) {
2015-06-30 10:59:27 +00:00
if ( ZSTR_LEN ( member ) = = 0 ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access empty property " ) ;
2015-01-13 08:33:00 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access property started with ' \\ 0' " ) ;
2015-01-13 08:33:00 +00:00
}
}
return ZEND_WRONG_PROPERTY_INFO ;
}
if ( UNEXPECTED ( zend_hash_num_elements ( & ce - > properties_info ) = = 0 ) ) {
goto exit_dynamic ;
}
zv = zend_hash_find ( & ce - > properties_info , member ) ;
if ( EXPECTED ( zv ! = NULL ) ) {
property_info = ( zend_property_info * ) Z_PTR_P ( zv ) ;
flags = property_info - > flags ;
if ( UNEXPECTED ( ( flags & ZEND_ACC_SHADOW ) ! = 0 ) ) {
/* if it's a shadow - go to access it's private */
property_info = NULL ;
} else {
if ( EXPECTED ( zend_verify_property_access ( property_info , ce ) ! = 0 ) ) {
if ( UNEXPECTED ( ! ( flags & ZEND_ACC_CHANGED ) )
| | UNEXPECTED ( ( flags & ZEND_ACC_PRIVATE ) ) ) {
if ( UNEXPECTED ( ( flags & ZEND_ACC_STATIC ) ! = 0 ) ) {
if ( ! silent ) {
2015-06-30 10:59:27 +00:00
zend_error ( E_NOTICE , " Accessing static property %s::$%s as non static " , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( member ) ) ;
2015-01-13 08:33:00 +00:00
}
}
goto exit ;
}
} else {
/* Try to look in the scope instead */
property_info = ZEND_WRONG_PROPERTY_INFO ;
}
}
}
if ( EG ( scope ) ! = ce
& & EG ( scope )
& & is_derived_class ( ce , EG ( scope ) )
& & ( zv = zend_hash_find ( & EG ( scope ) - > properties_info , member ) ) ! = NULL
& & ( ( zend_property_info * ) Z_PTR_P ( zv ) ) - > flags & ZEND_ACC_PRIVATE ) {
property_info = ( zend_property_info * ) Z_PTR_P ( zv ) ;
} else if ( UNEXPECTED ( property_info = = NULL ) ) {
exit_dynamic :
return NULL ;
} else if ( UNEXPECTED ( property_info = = ZEND_WRONG_PROPERTY_INFO ) ) {
/* Information was available, but we were denied access. Error out. */
if ( ! silent ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access %s property %s::$%s " , zend_visibility_string ( flags ) , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( member ) ) ;
2015-01-13 08:33:00 +00:00
}
return ZEND_WRONG_PROPERTY_INFO ;
}
exit :
return property_info ;
2010-04-20 10:57:45 +00:00
}
/* }}} */
2014-12-13 22:06:14 +00:00
ZEND_API int zend_check_property_access ( zend_object * zobj , zend_string * prop_info_name ) /* { { { */
2003-12-18 20:07:30 +00:00
{
zend_property_info * property_info ;
2014-04-01 19:27:51 +00:00
const char * class_name = NULL ;
const char * prop_name ;
zend_string * member ;
2014-09-15 22:23:58 +00:00
size_t prop_name_len ;
2003-12-18 20:07:30 +00:00
2015-06-30 10:59:27 +00:00
if ( ZSTR_VAL ( prop_info_name ) [ 0 ] = = 0 ) {
2014-09-15 22:23:58 +00:00
zend_unmangle_property_name_ex ( prop_info_name , & class_name , & prop_name , & prop_name_len ) ;
2014-08-25 17:24:55 +00:00
member = zend_string_init ( prop_name , prop_name_len , 0 ) ;
2014-04-01 19:27:51 +00:00
} else {
2014-08-25 17:24:55 +00:00
member = zend_string_copy ( prop_info_name ) ;
2014-04-01 19:27:51 +00:00
}
2015-01-13 08:33:00 +00:00
property_info = zend_get_property_info ( zobj - > ce , member , 1 ) ;
2014-08-25 17:24:55 +00:00
zend_string_release ( member ) ;
2014-10-17 15:10:05 +00:00
if ( property_info = = NULL ) {
/* undefined public property */
if ( class_name & & class_name [ 0 ] ! = ' * ' ) {
/* we we're looking for a private prop */
return FAILURE ;
}
return SUCCESS ;
} else if ( property_info = = ZEND_WRONG_PROPERTY_INFO ) {
2003-12-18 20:07:30 +00:00
return FAILURE ;
}
2007-11-02 19:40:39 +00:00
if ( class_name & & class_name [ 0 ] ! = ' * ' ) {
2005-06-06 07:52:08 +00:00
if ( ! ( property_info - > flags & ZEND_ACC_PRIVATE ) ) {
/* we we're looking for a private prop but found a non private one of the same name */
return FAILURE ;
2015-06-30 10:59:27 +00:00
} else if ( strcmp ( ZSTR_VAL ( prop_info_name ) + 1 , ZSTR_VAL ( property_info - > name ) + 1 ) ) {
2005-06-06 07:52:08 +00:00
/* we we're looking for a private prop but found a private one of the same name but another class */
return FAILURE ;
}
2003-12-18 20:07:30 +00:00
}
2014-12-13 22:06:14 +00:00
return zend_verify_property_access ( property_info , zobj - > ce ) ? SUCCESS : FAILURE ;
2003-12-18 20:07:30 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-12-18 20:07:30 +00:00
2015-01-31 10:12:31 +00:00
static void zend_property_guard_dtor ( zval * el ) /* { { { */ {
2015-09-10 08:22:07 +00:00
efree_size ( Z_PTR_P ( el ) , sizeof ( zend_ulong ) ) ;
2015-01-31 10:12:31 +00:00
}
/* }}} */
2014-10-17 15:10:05 +00:00
static zend_long * zend_get_property_guard ( zend_object * zobj , zend_string * member ) /* { { { */
2005-11-15 13:35:23 +00:00
{
2015-02-04 12:24:13 +00:00
HashTable * guards ;
2015-01-31 10:12:31 +00:00
zend_long stub , * guard ;
2015-02-04 12:24:13 +00:00
ZEND_ASSERT ( GC_FLAGS ( zobj ) & IS_OBJ_USE_GUARDS ) ;
if ( GC_FLAGS ( zobj ) & IS_OBJ_HAS_GUARDS ) {
guards = Z_PTR ( zobj - > properties_table [ zobj - > ce - > default_properties_count ] ) ;
ZEND_ASSERT ( guards ! = NULL ) ;
if ( ( guard = ( zend_long * ) zend_hash_find_ptr ( guards , member ) ) ! = NULL ) {
return guard ;
}
} else {
ALLOC_HASHTABLE ( guards ) ;
zend_hash_init ( guards , 8 , NULL , zend_property_guard_dtor , 0 ) ;
Z_PTR ( zobj - > properties_table [ zobj - > ce - > default_properties_count ] ) = guards ;
GC_FLAGS ( zobj ) | = IS_OBJ_HAS_GUARDS ;
2014-02-10 06:04:30 +00:00
}
2015-01-31 10:12:31 +00:00
stub = 0 ;
2015-02-04 12:24:13 +00:00
return ( zend_long * ) zend_hash_add_mem ( guards , member , & stub , sizeof ( zend_ulong ) ) ;
2005-11-15 13:35:23 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2005-11-15 13:35:23 +00:00
2014-12-13 22:06:14 +00:00
zval * zend_std_read_property ( zval * object , zval * member , int type , void * * cache_slot , zval * rv ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
2014-02-10 06:04:30 +00:00
zval tmp_member ;
zval * retval ;
2015-01-13 08:33:00 +00:00
uint32_t property_offset ;
2004-03-21 18:07:27 +00:00
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2002-02-07 14:08:43 +00:00
2014-02-10 06:04:30 +00:00
ZVAL_UNDEF ( & tmp_member ) ;
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( Z_TYPE_P ( member ) ! = IS_STRING ) ) {
2014-10-06 16:45:08 +00:00
ZVAL_STR ( & tmp_member , zval_get_string ( member ) ) ;
2014-02-10 06:04:30 +00:00
member = & tmp_member ;
2014-07-07 16:54:31 +00:00
cache_slot = NULL ;
2002-02-07 14:08:43 +00:00
}
# if DEBUG_OBJECT_HANDLERS
fprintf ( stderr , " Read object #%d property: %s \n " , Z_OBJ_HANDLE_P ( object ) , Z_STRVAL_P ( member ) ) ;
2007-10-11 01:03:19 +00:00
# endif
2003-02-04 12:12:34 +00:00
2004-07-19 14:26:53 +00:00
/* make zend_get_property_info silent if we have getter - we may want to use it */
2015-01-13 08:33:00 +00:00
property_offset = zend_get_property_offset ( zobj - > ce , Z_STR_P ( member ) , ( type = = BP_VAR_IS ) | | ( zobj - > ce - > __get ! = NULL ) , cache_slot ) ;
2003-02-04 12:12:34 +00:00
2015-01-13 08:33:00 +00:00
if ( EXPECTED ( property_offset ! = ZEND_WRONG_PROPERTY_OFFSET ) ) {
if ( EXPECTED ( property_offset ! = ZEND_DYNAMIC_PROPERTY_OFFSET ) ) {
retval = OBJ_PROP ( zobj , property_offset ) ;
2014-10-20 16:33:35 +00:00
if ( EXPECTED ( Z_TYPE_P ( retval ) ! = IS_UNDEF ) ) {
2014-03-26 14:07:31 +00:00
goto exit ;
2014-02-21 18:59:51 +00:00
}
2014-10-20 16:33:35 +00:00
} else if ( EXPECTED ( zobj - > properties ! = NULL ) ) {
2014-10-17 15:10:05 +00:00
retval = zend_hash_find ( zobj - > properties , Z_STR_P ( member ) ) ;
2014-10-20 16:33:35 +00:00
if ( EXPECTED ( retval ) ) goto exit ;
2014-02-10 06:04:30 +00:00
}
2015-03-31 21:37:59 +00:00
} else if ( UNEXPECTED ( EG ( exception ) ) ) {
retval = & EG ( uninitialized_zval ) ;
goto exit ;
2014-02-10 06:04:30 +00:00
}
2016-03-26 10:43:56 +00:00
/* magic isset */
if ( ( type = = BP_VAR_IS ) & & zobj - > ce - > __isset ) {
zval tmp_object , tmp_result ;
zend_long * guard = zend_get_property_guard ( zobj , Z_STR_P ( member ) ) ;
if ( ! ( ( * guard ) & IN_ISSET ) ) {
ZVAL_COPY ( & tmp_object , object ) ;
ZVAL_UNDEF ( & tmp_result ) ;
* guard | = IN_ISSET ;
zend_std_call_issetter ( & tmp_object , member , & tmp_result ) ;
* guard & = ~ IN_ISSET ;
if ( ! zend_is_true ( & tmp_result ) ) {
retval = & EG ( uninitialized_zval ) ;
zval_ptr_dtor ( & tmp_object ) ;
zval_ptr_dtor ( & tmp_result ) ;
goto exit ;
}
zval_ptr_dtor ( & tmp_object ) ;
zval_ptr_dtor ( & tmp_result ) ;
}
}
2014-03-26 14:07:31 +00:00
/* magic get */
2014-02-10 06:04:30 +00:00
if ( zobj - > ce - > __get ) {
2014-10-17 15:10:05 +00:00
zend_long * guard = zend_get_property_guard ( zobj , Z_STR_P ( member ) ) ;
2014-02-10 06:04:30 +00:00
if ( ! ( ( * guard ) & IN_GET ) ) {
2014-04-16 14:06:03 +00:00
zval tmp_object ;
2002-09-04 09:07:58 +00:00
/* have getter - try with it! */
2014-04-16 14:06:03 +00:00
ZVAL_COPY ( & tmp_object , object ) ;
2014-02-10 06:04:30 +00:00
* guard | = IN_GET ; /* prevent circular getting */
2014-12-13 22:06:14 +00:00
zend_std_call_getter ( & tmp_object , member , rv ) ;
2014-02-10 06:04:30 +00:00
* guard & = ~ IN_GET ;
2002-09-04 09:07:58 +00:00
2014-02-27 11:40:13 +00:00
if ( Z_TYPE_P ( rv ) ! = IS_UNDEF ) {
retval = rv ;
2007-10-07 05:22:07 +00:00
if ( ! Z_ISREF_P ( rv ) & &
2007-01-10 15:58:08 +00:00
( type = = BP_VAR_W | | type = = BP_VAR_RW | | type = = BP_VAR_UNSET ) ) {
2014-04-15 21:45:40 +00:00
SEPARATE_ZVAL ( rv ) ;
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( Z_TYPE_P ( rv ) ! = IS_OBJECT ) ) {
2015-06-30 10:59:27 +00:00
zend_error ( E_NOTICE , " Indirect modification of overloaded property %s::$%s has no effect " , ZSTR_VAL ( zobj - > ce - > name ) , Z_STRVAL_P ( member ) ) ;
2006-07-21 10:32:17 +00:00
}
}
2002-09-04 09:07:58 +00:00
} else {
2014-02-27 11:40:13 +00:00
retval = & EG ( uninitialized_zval ) ;
2002-09-04 09:07:58 +00:00
}
2014-04-16 14:06:03 +00:00
zval_ptr_dtor ( & tmp_object ) ;
2014-10-17 15:10:05 +00:00
goto exit ;
2002-09-04 09:07:58 +00:00
} else {
2014-02-10 06:04:30 +00:00
if ( Z_STRVAL_P ( member ) [ 0 ] = = ' \0 ' ) {
2014-08-25 17:24:55 +00:00
if ( Z_STRLEN_P ( member ) = = 0 ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access empty property " ) ;
2015-03-31 21:37:59 +00:00
retval = & EG ( uninitialized_zval ) ;
goto exit ;
2014-02-10 06:04:30 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access property started with ' \\ 0' " ) ;
2015-03-31 21:37:59 +00:00
retval = & EG ( uninitialized_zval ) ;
goto exit ;
2010-08-01 13:27:02 +00:00
}
}
2014-02-10 06:04:30 +00:00
}
2002-02-07 14:08:43 +00:00
}
2014-10-17 15:10:05 +00:00
if ( ( type ! = BP_VAR_IS ) ) {
2015-06-30 10:59:27 +00:00
zend_error ( E_NOTICE , " Undefined property: %s::$%s " , ZSTR_VAL ( zobj - > ce - > name ) , Z_STRVAL_P ( member ) ) ;
2014-10-17 15:10:05 +00:00
}
retval = & EG ( uninitialized_zval ) ;
2014-03-26 14:07:31 +00:00
2014-02-10 06:04:30 +00:00
exit :
2015-09-10 06:57:22 +00:00
if ( UNEXPECTED ( Z_REFCOUNTED ( tmp_member ) ) ) {
2005-06-03 11:16:19 +00:00
zval_ptr_dtor ( & tmp_member ) ;
2002-02-07 14:08:43 +00:00
}
2015-09-10 06:39:25 +00:00
2014-02-10 06:04:30 +00:00
return retval ;
2002-02-07 14:08:43 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2014-12-13 22:06:14 +00:00
ZEND_API void zend_std_write_property ( zval * object , zval * member , zval * value , void * * cache_slot ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
2014-02-10 06:04:30 +00:00
zval tmp_member ;
zval * variable_ptr ;
2015-01-13 08:33:00 +00:00
uint32_t property_offset ;
2004-07-19 14:26:53 +00:00
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2002-02-07 14:08:43 +00:00
2014-02-10 06:04:30 +00:00
ZVAL_UNDEF ( & tmp_member ) ;
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( Z_TYPE_P ( member ) ! = IS_STRING ) ) {
2014-10-06 16:45:08 +00:00
ZVAL_STR ( & tmp_member , zval_get_string ( member ) ) ;
2014-02-10 06:04:30 +00:00
member = & tmp_member ;
2014-07-07 16:54:31 +00:00
cache_slot = NULL ;
2002-02-07 14:08:43 +00:00
}
2015-01-13 08:33:00 +00:00
property_offset = zend_get_property_offset ( zobj - > ce , Z_STR_P ( member ) , ( zobj - > ce - > __set ! = NULL ) , cache_slot ) ;
2003-02-04 12:12:34 +00:00
2015-01-13 08:33:00 +00:00
if ( EXPECTED ( property_offset ! = ZEND_WRONG_PROPERTY_OFFSET ) ) {
if ( EXPECTED ( property_offset ! = ZEND_DYNAMIC_PROPERTY_OFFSET ) ) {
variable_ptr = OBJ_PROP ( zobj , property_offset ) ;
2014-03-26 14:07:31 +00:00
if ( Z_TYPE_P ( variable_ptr ) ! = IS_UNDEF ) {
goto found ;
2014-02-21 18:59:51 +00:00
}
2014-03-26 14:07:31 +00:00
} else if ( EXPECTED ( zobj - > properties ! = NULL ) ) {
2015-06-17 09:50:16 +00:00
if ( UNEXPECTED ( GC_REFCOUNT ( zobj - > properties ) > 1 ) ) {
if ( EXPECTED ( ! ( GC_FLAGS ( zobj - > properties ) & IS_ARRAY_IMMUTABLE ) ) ) {
GC_REFCOUNT ( zobj - > properties ) - - ;
}
zobj - > properties = zend_array_dup ( zobj - > properties ) ;
}
2014-10-17 15:10:05 +00:00
if ( ( variable_ptr = zend_hash_find ( zobj - > properties , Z_STR_P ( member ) ) ) ! = NULL ) {
2014-02-10 06:04:30 +00:00
found :
2015-04-02 22:32:20 +00:00
zend_assign_to_variable ( variable_ptr , value , IS_CV ) ;
2014-03-26 14:07:31 +00:00
goto exit ;
2002-02-07 14:08:43 +00:00
}
}
2015-03-31 21:37:59 +00:00
} else if ( UNEXPECTED ( EG ( exception ) ) ) {
goto exit ;
2014-02-10 06:04:30 +00:00
}
2014-03-26 14:07:31 +00:00
/* magic set */
2014-02-10 06:04:30 +00:00
if ( zobj - > ce - > __set ) {
2014-10-17 15:10:05 +00:00
zend_long * guard = zend_get_property_guard ( zobj , Z_STR_P ( member ) ) ;
2005-11-15 13:35:23 +00:00
2014-02-10 06:04:30 +00:00
if ( ! ( ( * guard ) & IN_SET ) ) {
2014-04-16 14:06:03 +00:00
zval tmp_object ;
ZVAL_COPY ( & tmp_object , object ) ;
2014-02-10 06:04:30 +00:00
( * guard ) | = IN_SET ; /* prevent circular setting */
2014-12-13 22:06:14 +00:00
if ( zend_std_call_setter ( & tmp_object , member , value ) ! = SUCCESS ) {
2002-09-09 08:59:18 +00:00
/* for now, just ignore it - __set should take care of warnings, etc. */
2002-09-04 09:07:58 +00:00
}
2014-02-10 06:04:30 +00:00
( * guard ) & = ~ IN_SET ;
2014-04-16 14:06:03 +00:00
zval_ptr_dtor ( & tmp_object ) ;
2015-01-13 08:33:00 +00:00
} else if ( EXPECTED ( property_offset ! = ZEND_WRONG_PROPERTY_OFFSET ) ) {
2014-03-06 22:03:25 +00:00
goto write_std_property ;
2014-02-10 06:04:30 +00:00
} else {
2010-10-01 09:49:20 +00:00
if ( Z_STRVAL_P ( member ) [ 0 ] = = ' \0 ' ) {
2014-08-25 17:24:55 +00:00
if ( Z_STRLEN_P ( member ) = = 0 ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access empty property " ) ;
2015-03-31 21:37:59 +00:00
goto exit ;
2010-10-01 09:49:20 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access property started with ' \\ 0' " ) ;
2015-03-31 21:37:59 +00:00
goto exit ;
2010-10-01 09:49:20 +00:00
}
}
2002-10-09 17:14:25 +00:00
}
2015-01-13 08:33:00 +00:00
} else if ( EXPECTED ( property_offset ! = ZEND_WRONG_PROPERTY_OFFSET ) ) {
2014-09-13 21:30:32 +00:00
zval tmp ;
2014-03-06 22:03:25 +00:00
write_std_property :
2014-03-05 09:55:56 +00:00
if ( Z_REFCOUNTED_P ( value ) ) {
2014-02-19 08:03:01 +00:00
if ( Z_ISREF_P ( value ) ) {
2014-09-13 21:30:32 +00:00
/* if we assign referenced variable, we should separate it */
2015-06-11 17:41:43 +00:00
ZVAL_COPY ( & tmp , Z_REFVAL_P ( value ) ) ;
2014-03-18 08:37:51 +00:00
value = & tmp ;
2014-03-04 20:28:01 +00:00
} else {
Z_ADDREF_P ( value ) ;
2014-02-19 08:03:01 +00:00
}
2014-02-10 06:04:30 +00:00
}
2015-01-13 08:33:00 +00:00
if ( EXPECTED ( property_offset ! = ZEND_DYNAMIC_PROPERTY_OFFSET ) ) {
ZVAL_COPY_VALUE ( OBJ_PROP ( zobj , property_offset ) , value ) ;
2014-02-10 06:04:30 +00:00
} else {
if ( ! zobj - > properties ) {
rebuild_object_properties ( zobj ) ;
}
2014-11-06 14:45:14 +00:00
zend_hash_add_new ( zobj - > properties , Z_STR_P ( member ) , value ) ;
2014-02-10 06:04:30 +00:00
}
2002-09-04 09:07:58 +00:00
}
2006-07-26 15:29:27 +00:00
2014-03-26 14:07:31 +00:00
exit :
2015-09-10 06:57:22 +00:00
if ( UNEXPECTED ( Z_REFCOUNTED ( tmp_member ) ) ) {
2005-06-03 11:16:19 +00:00
zval_ptr_dtor ( & tmp_member ) ;
2002-02-07 14:08:43 +00:00
}
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2014-12-13 22:06:14 +00:00
zval * zend_std_read_dimension ( zval * object , zval * offset , int type , zval * rv ) /* { { { */
2003-07-07 10:53:27 +00:00
{
2003-11-24 20:57:54 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2014-02-27 11:40:13 +00:00
zval tmp ;
2006-05-09 23:53:23 +00:00
2014-12-13 22:06:14 +00:00
if ( EXPECTED ( instanceof_function_ex ( ce , zend_ce_arrayaccess , 1 ) ! = 0 ) ) {
2016-03-20 12:33:00 +00:00
if ( offset = = NULL ) {
2004-07-14 09:01:58 +00:00
/* [] construct */
2016-03-20 11:58:58 +00:00
ZVAL_NULL ( & tmp ) ;
2014-02-10 06:04:30 +00:00
offset = & tmp ;
2005-02-02 07:19:22 +00:00
} else {
SEPARATE_ARG_IF_REF ( offset ) ;
2004-07-14 09:01:58 +00:00
}
2016-03-20 12:33:00 +00:00
if ( type = = BP_VAR_IS ) {
zend_call_method_with_1_params ( object , ce , NULL , " offsetexists " , rv , offset ) ;
if ( UNEXPECTED ( Z_ISUNDEF_P ( rv ) ) ) {
return NULL ;
}
if ( ! i_zend_is_true ( rv ) ) {
zval_ptr_dtor ( rv ) ;
return & EG ( uninitialized_zval ) ;
}
zval_ptr_dtor ( rv ) ;
}
2014-02-27 11:40:13 +00:00
zend_call_method_with_1_params ( object , ce , NULL , " offsetget " , rv , offset ) ;
2004-07-14 09:04:13 +00:00
2014-02-10 06:04:30 +00:00
zval_ptr_dtor ( offset ) ;
2005-02-02 07:19:22 +00:00
2014-02-27 11:40:13 +00:00
if ( UNEXPECTED ( Z_TYPE_P ( rv ) = = IS_UNDEF ) ) {
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( ! EG ( exception ) ) ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Undefined offset for object of type %s used as array " , ZSTR_VAL ( ce - > name ) ) ;
2003-12-11 09:56:06 +00:00
}
2014-02-10 06:04:30 +00:00
return NULL ;
2003-12-11 09:56:06 +00:00
}
2014-02-27 11:40:13 +00:00
return rv ;
2003-11-24 20:57:54 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot use object of type %s as array " , ZSTR_VAL ( ce - > name ) ) ;
2014-02-10 06:04:30 +00:00
return NULL ;
2003-11-24 20:57:54 +00:00
}
2003-07-07 10:53:27 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-07-07 10:53:27 +00:00
2014-12-13 22:06:14 +00:00
static void zend_std_write_dimension ( zval * object , zval * offset , zval * value ) /* { { { */
2003-07-07 09:00:36 +00:00
{
2003-11-24 20:57:54 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2014-02-10 06:04:30 +00:00
zval tmp ;
2005-02-02 07:19:22 +00:00
2014-12-13 22:06:14 +00:00
if ( EXPECTED ( instanceof_function_ex ( ce , zend_ce_arrayaccess , 1 ) ! = 0 ) ) {
2003-12-22 16:27:14 +00:00
if ( ! offset ) {
2014-03-04 12:07:42 +00:00
ZVAL_NULL ( & tmp ) ;
2014-02-10 06:04:30 +00:00
offset = & tmp ;
2005-02-02 07:19:22 +00:00
} else {
SEPARATE_ARG_IF_REF ( offset ) ;
2003-12-22 16:27:14 +00:00
}
2014-02-10 06:04:30 +00:00
zend_call_method_with_2_params ( object , ce , NULL , " offsetset " , NULL , offset , value ) ;
zval_ptr_dtor ( offset ) ;
2003-11-24 20:57:54 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot use object of type %s as array " , ZSTR_VAL ( ce - > name ) ) ;
2003-11-24 20:57:54 +00:00
}
2003-07-07 09:00:36 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-07-07 09:00:36 +00:00
2014-12-13 22:06:14 +00:00
static int zend_std_has_dimension ( zval * object , zval * offset , int check_empty ) /* { { { */
2003-11-10 16:14:44 +00:00
{
2003-11-24 20:57:54 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2014-02-10 06:04:30 +00:00
zval retval ;
2003-11-24 20:57:54 +00:00
int result ;
2006-05-09 23:53:23 +00:00
2014-12-13 22:06:14 +00:00
if ( EXPECTED ( instanceof_function_ex ( ce , zend_ce_arrayaccess , 1 ) ! = 0 ) ) {
2005-02-02 07:19:22 +00:00
SEPARATE_ARG_IF_REF ( offset ) ;
2014-02-10 06:04:30 +00:00
zend_call_method_with_1_params ( object , ce , NULL , " offsetexists " , & retval , offset ) ;
if ( EXPECTED ( Z_TYPE ( retval ) ! = IS_UNDEF ) ) {
2014-12-13 22:06:14 +00:00
result = i_zend_is_true ( & retval ) ;
2005-03-19 15:32:18 +00:00
zval_ptr_dtor ( & retval ) ;
2010-05-06 12:52:27 +00:00
if ( check_empty & & result & & EXPECTED ( ! EG ( exception ) ) ) {
2014-02-10 06:04:30 +00:00
zend_call_method_with_1_params ( object , ce , NULL , " offsetget " , & retval , offset ) ;
if ( EXPECTED ( Z_TYPE ( retval ) ! = IS_UNDEF ) ) {
2014-12-13 22:06:14 +00:00
result = i_zend_is_true ( & retval ) ;
2005-07-07 16:07:09 +00:00
zval_ptr_dtor ( & retval ) ;
}
}
2005-03-19 15:32:18 +00:00
} else {
2005-07-07 16:07:09 +00:00
result = 0 ;
2005-03-19 15:32:18 +00:00
}
2014-02-10 06:04:30 +00:00
zval_ptr_dtor ( offset ) ;
2003-11-24 20:57:54 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot use object of type %s as array " , ZSTR_VAL ( ce - > name ) ) ;
2003-11-24 20:57:54 +00:00
return 0 ;
}
2005-07-07 16:07:09 +00:00
return result ;
2003-11-10 16:14:44 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-11-10 16:14:44 +00:00
2014-12-13 22:06:14 +00:00
static zval * zend_std_get_property_ptr_ptr ( zval * object , zval * member , int type , void * * cache_slot ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
2014-10-17 15:10:05 +00:00
zend_string * name ;
zval * retval = NULL ;
2015-01-13 08:33:00 +00:00
uint32_t property_offset ;
2006-05-09 23:53:23 +00:00
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2014-10-17 15:10:05 +00:00
if ( EXPECTED ( Z_TYPE_P ( member ) = = IS_STRING ) ) {
name = Z_STR_P ( member ) ;
} else {
name = zval_get_string ( member ) ;
2002-02-07 14:08:43 +00:00
}
# if DEBUG_OBJECT_HANDLERS
2015-06-30 10:59:27 +00:00
fprintf ( stderr , " Ptr object #%d property: %s \n " , Z_OBJ_HANDLE_P ( object ) , ZSTR_VAL ( name ) ) ;
2006-05-09 23:53:23 +00:00
# endif
2002-02-07 14:08:43 +00:00
2015-01-13 08:33:00 +00:00
property_offset = zend_get_property_offset ( zobj - > ce , name , ( zobj - > ce - > __get ! = NULL ) , cache_slot ) ;
2003-02-05 09:41:31 +00:00
2015-01-13 08:33:00 +00:00
if ( EXPECTED ( property_offset ! = ZEND_WRONG_PROPERTY_OFFSET ) ) {
if ( EXPECTED ( property_offset ! = ZEND_DYNAMIC_PROPERTY_OFFSET ) ) {
retval = OBJ_PROP ( zobj , property_offset ) ;
2014-10-17 15:10:05 +00:00
if ( UNEXPECTED ( Z_TYPE_P ( retval ) = = IS_UNDEF ) ) {
if ( EXPECTED ( ! zobj - > ce - > __get ) | |
UNEXPECTED ( ( * zend_get_property_guard ( zobj , name ) ) & IN_GET ) ) {
ZVAL_NULL ( retval ) ;
/* Notice is thrown after creation of the property, to avoid EG(std_property_info)
* being overwritten in an error handler . */
if ( UNEXPECTED ( type = = BP_VAR_RW | | type = = BP_VAR_R ) ) {
2015-06-30 10:59:27 +00:00
zend_error ( E_NOTICE , " Undefined property: %s::$%s " , ZSTR_VAL ( zobj - > ce - > name ) , ZSTR_VAL ( name ) ) ;
2014-10-17 15:10:05 +00:00
}
} else {
/* we do have getter - fail and let it try again with usual get/set */
retval = NULL ;
}
}
2002-09-04 09:07:58 +00:00
} else {
2015-06-17 09:50:16 +00:00
if ( EXPECTED ( zobj - > properties ) ) {
if ( UNEXPECTED ( GC_REFCOUNT ( zobj - > properties ) > 1 ) ) {
if ( EXPECTED ( ! ( GC_FLAGS ( zobj - > properties ) & IS_ARRAY_IMMUTABLE ) ) ) {
GC_REFCOUNT ( zobj - > properties ) - - ;
2014-10-17 15:10:05 +00:00
}
2015-06-17 09:50:16 +00:00
zobj - > properties = zend_array_dup ( zobj - > properties ) ;
}
if ( EXPECTED ( ( retval = zend_hash_find ( zobj - > properties , name ) ) ! = NULL ) ) {
if ( UNEXPECTED ( Z_TYPE_P ( member ) ! = IS_STRING ) ) {
zend_string_release ( name ) ;
2014-10-17 15:10:05 +00:00
}
2015-06-17 09:50:16 +00:00
return retval ;
}
}
if ( EXPECTED ( ! zobj - > ce - > __get ) | |
UNEXPECTED ( ( * zend_get_property_guard ( zobj , name ) ) & IN_GET ) ) {
if ( UNEXPECTED ( ! zobj - > properties ) ) {
rebuild_object_properties ( zobj ) ;
}
retval = zend_hash_update ( zobj - > properties , name , & EG ( uninitialized_zval ) ) ;
/* Notice is thrown after creation of the property, to avoid EG(std_property_info)
* being overwritten in an error handler . */
if ( UNEXPECTED ( type = = BP_VAR_RW | | type = = BP_VAR_R ) ) {
2015-06-30 10:59:27 +00:00
zend_error ( E_NOTICE , " Undefined property: %s::$%s " , ZSTR_VAL ( zobj - > ce - > name ) , ZSTR_VAL ( name ) ) ;
2015-06-17 09:50:16 +00:00
}
2014-02-10 06:04:30 +00:00
}
2002-09-04 09:07:58 +00:00
}
2002-02-07 14:08:43 +00:00
}
2014-02-10 06:04:30 +00:00
2014-10-17 15:10:05 +00:00
if ( UNEXPECTED ( Z_TYPE_P ( member ) ! = IS_STRING ) ) {
zend_string_release ( name ) ;
2002-02-07 14:08:43 +00:00
}
return retval ;
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2014-12-13 22:06:14 +00:00
static void zend_std_unset_property ( zval * object , zval * member , void * * cache_slot ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
2014-02-10 06:04:30 +00:00
zval tmp_member ;
2015-01-13 08:33:00 +00:00
uint32_t property_offset ;
2006-05-09 23:53:23 +00:00
2002-04-22 14:22:27 +00:00
zobj = Z_OBJ_P ( object ) ;
2002-02-07 14:08:43 +00:00
2014-02-10 06:04:30 +00:00
ZVAL_UNDEF ( & tmp_member ) ;
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( Z_TYPE_P ( member ) ! = IS_STRING ) ) {
2014-10-06 16:45:08 +00:00
ZVAL_STR ( & tmp_member , zval_get_string ( member ) ) ;
2014-02-10 06:04:30 +00:00
member = & tmp_member ;
2014-07-07 16:54:31 +00:00
cache_slot = NULL ;
2002-02-07 14:08:43 +00:00
}
2003-02-05 14:27:30 +00:00
2015-01-13 08:33:00 +00:00
property_offset = zend_get_property_offset ( zobj - > ce , Z_STR_P ( member ) , ( zobj - > ce - > __unset ! = NULL ) , cache_slot ) ;
2006-05-09 23:53:23 +00:00
2015-01-13 08:33:00 +00:00
if ( EXPECTED ( property_offset ! = ZEND_WRONG_PROPERTY_OFFSET ) ) {
if ( EXPECTED ( property_offset ! = ZEND_DYNAMIC_PROPERTY_OFFSET ) ) {
zval * slot = OBJ_PROP ( zobj , property_offset ) ;
2014-10-17 15:10:05 +00:00
2014-11-06 11:50:03 +00:00
if ( Z_TYPE_P ( slot ) ! = IS_UNDEF ) {
zval_ptr_dtor ( slot ) ;
ZVAL_UNDEF ( slot ) ;
2015-08-26 00:27:05 +00:00
if ( zobj - > properties ) {
zobj - > properties - > u . v . flags | = HASH_FLAG_HAS_EMPTY_IND ;
}
2014-03-26 14:07:31 +00:00
goto exit ;
}
2015-06-17 09:50:16 +00:00
} else if ( EXPECTED ( zobj - > properties ! = NULL ) ) {
if ( UNEXPECTED ( GC_REFCOUNT ( zobj - > properties ) > 1 ) ) {
if ( EXPECTED ( ! ( GC_FLAGS ( zobj - > properties ) & IS_ARRAY_IMMUTABLE ) ) ) {
GC_REFCOUNT ( zobj - > properties ) - - ;
}
zobj - > properties = zend_array_dup ( zobj - > properties ) ;
}
if ( EXPECTED ( zend_hash_del ( zobj - > properties , Z_STR_P ( member ) ) ! = FAILURE ) ) {
goto exit ;
}
2014-03-26 14:07:31 +00:00
}
2015-03-31 21:37:59 +00:00
} else if ( UNEXPECTED ( EG ( exception ) ) ) {
goto exit ;
2014-02-10 06:04:30 +00:00
}
2015-01-03 09:22:58 +00:00
2014-03-26 14:07:31 +00:00
/* magic unset */
if ( zobj - > ce - > __unset ) {
2014-10-17 15:10:05 +00:00
zend_long * guard = zend_get_property_guard ( zobj , Z_STR_P ( member ) ) ;
2014-03-26 14:07:31 +00:00
if ( ! ( ( * guard ) & IN_UNSET ) ) {
2014-04-16 14:06:03 +00:00
zval tmp_object ;
2014-03-26 14:07:31 +00:00
/* have unseter - try with it! */
2014-04-16 14:06:03 +00:00
ZVAL_COPY ( & tmp_object , object ) ;
2014-03-26 14:07:31 +00:00
( * guard ) | = IN_UNSET ; /* prevent circular unsetting */
2014-12-13 22:06:14 +00:00
zend_std_call_unsetter ( & tmp_object , member ) ;
2014-03-26 14:07:31 +00:00
( * guard ) & = ~ IN_UNSET ;
2014-04-16 14:06:03 +00:00
zval_ptr_dtor ( & tmp_object ) ;
2014-03-26 14:07:31 +00:00
} else {
if ( Z_STRVAL_P ( member ) [ 0 ] = = ' \0 ' ) {
2014-08-25 17:24:55 +00:00
if ( Z_STRLEN_P ( member ) = = 0 ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access empty property " ) ;
2015-03-31 21:37:59 +00:00
goto exit ;
2014-03-26 14:07:31 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access property started with ' \\ 0' " ) ;
2015-03-31 21:37:59 +00:00
goto exit ;
2010-08-01 13:27:02 +00:00
}
}
2005-07-07 16:07:09 +00:00
}
}
2014-02-10 06:04:30 +00:00
exit :
2015-09-10 06:57:22 +00:00
if ( UNEXPECTED ( Z_REFCOUNTED ( tmp_member ) ) ) {
2005-07-07 16:07:09 +00:00
zval_ptr_dtor ( & tmp_member ) ;
2002-02-07 14:08:43 +00:00
}
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2014-12-13 22:06:14 +00:00
static void zend_std_unset_dimension ( zval * object , zval * offset ) /* { { { */
2003-07-30 17:12:06 +00:00
{
2003-11-24 20:57:54 +00:00
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2006-05-09 23:53:23 +00:00
2014-12-13 22:06:14 +00:00
if ( instanceof_function_ex ( ce , zend_ce_arrayaccess , 1 ) ) {
2005-02-02 07:19:22 +00:00
SEPARATE_ARG_IF_REF ( offset ) ;
2014-02-10 06:04:30 +00:00
zend_call_method_with_1_params ( object , ce , NULL , " offsetunset " , NULL , offset ) ;
zval_ptr_dtor ( offset ) ;
2003-11-24 20:57:54 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot use object of type %s as array " , ZSTR_VAL ( ce - > name ) ) ;
2003-11-24 20:57:54 +00:00
}
2003-07-30 17:12:06 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-07-30 17:12:06 +00:00
2003-02-02 16:17:25 +00:00
/* Ensures that we're allowed to call a private method.
* Returns the function address that should be called , or NULL
* if no such function exists .
*/
2014-12-13 22:06:14 +00:00
static inline zend_function * zend_check_private_int ( zend_function * fbc , zend_class_entry * ce , zend_string * function_name ) /* { { { */
2003-02-02 16:17:25 +00:00
{
2014-02-10 06:04:30 +00:00
zval * func ;
2003-02-02 16:17:25 +00:00
if ( ! ce ) {
return 0 ;
}
/* We may call a private function if:
* 1. The class of our object is the same as the scope , and the private
* function ( EX ( fbc ) ) has the same scope .
* 2. One of our parent classes are the same as the scope , and it contains
* a private function with the same name that has the same scope .
*/
if ( fbc - > common . scope = = ce & & EG ( scope ) = = ce ) {
/* rule #1 checks out ok, allow the function call */
return fbc ;
}
/* Check rule #2 */
ce = ce - > parent ;
while ( ce ) {
if ( ce = = EG ( scope ) ) {
2014-02-10 06:04:30 +00:00
if ( ( func = zend_hash_find ( & ce - > function_table , function_name ) ) ) {
fbc = Z_FUNC_P ( func ) ;
if ( fbc - > common . fn_flags & ZEND_ACC_PRIVATE
& & fbc - > common . scope = = EG ( scope ) ) {
return fbc ;
}
2003-02-02 16:17:25 +00:00
}
break ;
}
ce = ce - > parent ;
}
return NULL ;
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-02-02 16:17:25 +00:00
2014-12-13 22:06:14 +00:00
ZEND_API int zend_check_private ( zend_function * fbc , zend_class_entry * ce , zend_string * function_name ) /* { { { */
2005-04-27 15:45:36 +00:00
{
2014-12-13 22:06:14 +00:00
return zend_check_private_int ( fbc , ce , function_name ) ! = NULL ;
2005-04-27 15:45:36 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2005-04-27 15:45:36 +00:00
2003-02-02 16:17:25 +00:00
/* Ensures that we're allowed to call a protected method.
*/
2007-11-02 19:40:39 +00:00
ZEND_API int zend_check_protected ( zend_class_entry * ce , zend_class_entry * scope ) /* { { { */
2003-02-02 16:17:25 +00:00
{
zend_class_entry * fbc_scope = ce ;
/* Is the context that's calling the function, the same as one of
* the function ' s parents ?
*/
while ( fbc_scope ) {
if ( fbc_scope = = scope ) {
return 1 ;
}
fbc_scope = fbc_scope - > parent ;
}
/* Is the function's scope the same as our current object context,
* or any of the parents of our context ?
*/
while ( scope ) {
if ( scope = = ce ) {
return 1 ;
}
scope = scope - > parent ;
}
return 0 ;
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-02-02 16:17:25 +00:00
2015-04-10 20:01:00 +00:00
ZEND_API zend_function * zend_get_call_trampoline_func ( zend_class_entry * ce , zend_string * method_name , int is_static ) /* { { { */
2009-01-07 22:12:39 +00:00
{
2015-04-10 20:01:00 +00:00
zend_op_array * func ;
zend_function * fbc = is_static ? ce - > __callstatic : ce - > __call ;
ZEND_ASSERT ( fbc ) ;
if ( EXPECTED ( EG ( trampoline ) . common . function_name = = NULL ) ) {
func = & EG ( trampoline ) . op_array ;
} else {
func = ecalloc ( 1 , sizeof ( zend_op_array ) ) ;
}
func - > type = ZEND_USER_FUNCTION ;
2015-04-22 18:46:13 +00:00
func - > arg_flags [ 0 ] = 0 ;
func - > arg_flags [ 1 ] = 0 ;
func - > arg_flags [ 2 ] = 0 ;
2015-04-10 20:01:00 +00:00
func - > fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_PUBLIC ;
if ( is_static ) {
func - > fn_flags | = ZEND_ACC_STATIC ;
}
func - > this_var = - 1 ;
func - > opcodes = & EG ( call_trampoline_op ) ;
func - > prototype = fbc ;
2015-04-11 15:57:42 +00:00
func - > scope = fbc - > common . scope ;
2016-01-28 08:41:15 +00:00
/* reserve space for arguments, local and temorary variables */
func - > T = ( fbc - > type = = ZEND_USER_FUNCTION ) ? MAX ( fbc - > op_array . last_var + fbc - > op_array . T , 2 ) : 2 ;
2015-06-29 13:44:54 +00:00
func - > filename = ( fbc - > type = = ZEND_USER_FUNCTION ) ? fbc - > op_array . filename : ZSTR_EMPTY_ALLOC ( ) ;
2015-04-10 20:01:00 +00:00
func - > line_start = ( fbc - > type = = ZEND_USER_FUNCTION ) ? fbc - > op_array . line_start : 0 ;
func - > line_end = ( fbc - > type = = ZEND_USER_FUNCTION ) ? fbc - > op_array . line_end : 0 ;
2014-04-11 20:50:36 +00:00
//??? keep compatibility for "\0" characters
//??? see: Zend/tests/bug46238.phpt
2015-06-30 10:59:27 +00:00
if ( UNEXPECTED ( strlen ( ZSTR_VAL ( method_name ) ) ! = ZSTR_LEN ( method_name ) ) ) {
func - > function_name = zend_string_init ( ZSTR_VAL ( method_name ) , strlen ( ZSTR_VAL ( method_name ) ) , 0 ) ;
2014-04-11 20:50:36 +00:00
} else {
2015-04-10 20:01:00 +00:00
func - > function_name = zend_string_copy ( method_name ) ;
2014-04-11 20:50:36 +00:00
}
2009-01-07 22:12:39 +00:00
2015-04-10 20:01:00 +00:00
return ( zend_function * ) func ;
}
/* }}} */
static zend_always_inline zend_function * zend_get_user_call_function ( zend_class_entry * ce , zend_string * method_name ) /* { { { */
{
return zend_get_call_trampoline_func ( ce , method_name , 0 ) ;
2009-01-07 22:12:39 +00:00
}
/* }}} */
2014-12-13 22:06:14 +00:00
static union _zend_function * zend_std_get_method ( zend_object * * obj_ptr , zend_string * method_name , const zval * key ) /* { { { */
2002-02-07 14:08:43 +00:00
{
2014-03-27 22:11:22 +00:00
zend_object * zobj = * obj_ptr ;
2014-02-10 06:04:30 +00:00
zval * func ;
2003-02-02 16:17:25 +00:00
zend_function * fbc ;
2014-02-10 06:04:30 +00:00
zend_string * lc_method_name ;
2014-05-02 15:01:36 +00:00
ALLOCA_FLAG ( use_heap ) ;
2007-10-11 01:03:19 +00:00
2010-05-06 12:52:27 +00:00
if ( EXPECTED ( key ! = NULL ) ) {
2014-04-17 11:40:45 +00:00
lc_method_name = Z_STR_P ( key ) ;
2015-01-15 18:43:17 +00:00
# ifdef ZEND_ALLOCA_MAX_SIZE
2015-01-15 18:08:21 +00:00
use_heap = 0 ;
2015-01-15 18:43:17 +00:00
# endif
2010-04-20 10:57:45 +00:00
} else {
2015-06-30 10:59:27 +00:00
ZSTR_ALLOCA_ALLOC ( lc_method_name , ZSTR_LEN ( method_name ) , use_heap ) ;
zend_str_tolower_copy ( ZSTR_VAL ( lc_method_name ) , ZSTR_VAL ( method_name ) , ZSTR_LEN ( method_name ) ) ;
2010-04-20 10:57:45 +00:00
}
2007-10-11 01:03:19 +00:00
2014-02-10 06:04:30 +00:00
if ( UNEXPECTED ( ( func = zend_hash_find ( & zobj - > ce - > function_table , lc_method_name ) ) = = NULL ) ) {
2015-01-15 23:21:27 +00:00
if ( UNEXPECTED ( ! key ) ) {
2015-06-29 13:44:54 +00:00
ZSTR_ALLOCA_FREE ( lc_method_name , use_heap ) ;
2015-01-15 23:21:27 +00:00
}
2003-01-29 15:02:57 +00:00
if ( zobj - > ce - > __call ) {
2014-02-10 06:04:30 +00:00
return zend_get_user_call_function ( zobj - > ce , method_name ) ;
2003-01-29 15:02:57 +00:00
} else {
return NULL ;
2002-09-04 09:07:58 +00:00
}
2002-02-07 14:08:43 +00:00
}
2002-06-05 17:34:56 +00:00
2014-02-10 06:04:30 +00:00
fbc = Z_FUNC_P ( func ) ;
2003-02-02 16:17:25 +00:00
/* Check access level */
2006-09-12 11:01:16 +00:00
if ( fbc - > op_array . fn_flags & ZEND_ACC_PRIVATE ) {
zend_function * updated_fbc ;
/* Ensure that if we're calling a private function, we're allowed to do so.
2009-01-07 22:12:39 +00:00
* If we ' re not and __call ( ) handler exists , invoke it , otherwise error out .
2006-09-12 11:01:16 +00:00
*/
2014-12-13 22:06:14 +00:00
updated_fbc = zend_check_private_int ( fbc , zobj - > ce , lc_method_name ) ;
2010-05-06 12:52:27 +00:00
if ( EXPECTED ( updated_fbc ! = NULL ) ) {
2009-01-07 22:12:39 +00:00
fbc = updated_fbc ;
} else {
if ( zobj - > ce - > __call ) {
2014-02-10 06:04:30 +00:00
fbc = zend_get_user_call_function ( zobj - > ce , method_name ) ;
2009-01-07 22:12:39 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Call to %s method %s::%s() from context '%s' " , zend_visibility_string ( fbc - > common . fn_flags ) , ZEND_FN_SCOPE_NAME ( fbc ) , ZSTR_VAL ( method_name ) , EG ( scope ) ? ZSTR_VAL ( EG ( scope ) - > name ) : " " ) ;
2015-03-31 21:37:59 +00:00
fbc = NULL ;
2009-01-07 22:12:39 +00:00
}
2006-09-12 11:01:16 +00:00
}
} else {
2003-02-02 16:17:25 +00:00
/* Ensure that we haven't overridden a private function and end up calling
* the overriding public function . . .
*/
2007-07-12 10:32:09 +00:00
if ( EG ( scope ) & &
is_derived_class ( fbc - > common . scope , EG ( scope ) ) & &
fbc - > op_array . fn_flags & ZEND_ACC_CHANGED ) {
2014-05-18 09:28:06 +00:00
if ( ( func = zend_hash_find ( & EG ( scope ) - > function_table , lc_method_name ) ) ! = NULL ) {
2014-02-10 06:04:30 +00:00
zend_function * priv_fbc = Z_FUNC_P ( func ) ;
if ( priv_fbc - > common . fn_flags & ZEND_ACC_PRIVATE
& & priv_fbc - > common . scope = = EG ( scope ) ) {
fbc = priv_fbc ;
}
2003-02-02 16:17:25 +00:00
}
}
2006-09-12 11:01:16 +00:00
if ( ( fbc - > common . fn_flags & ZEND_ACC_PROTECTED ) ) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
2009-01-07 22:12:39 +00:00
* If we ' re not and __call ( ) handler exists , invoke it , otherwise error out .
2006-09-12 11:01:16 +00:00
*/
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( ! zend_check_protected ( zend_get_function_root_class ( fbc ) , EG ( scope ) ) ) ) {
2009-01-07 22:12:39 +00:00
if ( zobj - > ce - > __call ) {
2014-02-10 06:04:30 +00:00
fbc = zend_get_user_call_function ( zobj - > ce , method_name ) ;
2009-01-07 22:12:39 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Call to %s method %s::%s() from context '%s' " , zend_visibility_string ( fbc - > common . fn_flags ) , ZEND_FN_SCOPE_NAME ( fbc ) , ZSTR_VAL ( method_name ) , EG ( scope ) ? ZSTR_VAL ( EG ( scope ) - > name ) : " " ) ;
2015-03-31 21:37:59 +00:00
fbc = NULL ;
2009-01-07 22:12:39 +00:00
}
2006-09-12 11:01:16 +00:00
}
2003-02-02 16:17:25 +00:00
}
}
2015-01-15 23:21:27 +00:00
if ( UNEXPECTED ( ! key ) ) {
2015-06-29 13:44:54 +00:00
ZSTR_ALLOCA_FREE ( lc_method_name , use_heap ) ;
2015-01-15 23:21:27 +00:00
}
2003-02-02 16:17:25 +00:00
return fbc ;
2002-02-07 14:08:43 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2015-04-10 20:01:00 +00:00
static zend_always_inline zend_function * zend_get_user_callstatic_function ( zend_class_entry * ce , zend_string * method_name ) /* { { { */
2009-06-12 01:05:25 +00:00
{
2015-04-10 20:01:00 +00:00
return zend_get_call_trampoline_func ( ce , method_name , 1 ) ;
2009-06-12 01:05:25 +00:00
}
/* }}} */
2014-12-13 22:06:14 +00:00
ZEND_API zend_function * zend_std_get_static_method ( zend_class_entry * ce , zend_string * function_name , const zval * key ) /* { { { */
2003-02-02 16:17:25 +00:00
{
2008-03-17 14:54:42 +00:00
zend_function * fbc = NULL ;
2014-02-10 06:04:30 +00:00
char * lc_class_name ;
zend_string * lc_function_name ;
2015-04-23 09:16:37 +00:00
zend_object * object ;
2003-02-02 16:17:25 +00:00
2010-05-06 12:52:27 +00:00
if ( EXPECTED ( key ! = NULL ) ) {
2014-04-17 11:40:45 +00:00
lc_function_name = Z_STR_P ( key ) ;
2010-04-20 10:57:45 +00:00
} else {
2014-12-24 12:04:51 +00:00
lc_function_name = zend_string_tolower ( function_name ) ;
2010-04-20 10:57:45 +00:00
}
2012-05-13 05:12:48 +00:00
2015-06-30 10:59:27 +00:00
if ( ZSTR_LEN ( function_name ) = = ZSTR_LEN ( ce - > name ) & & ce - > constructor ) {
lc_class_name = zend_str_tolower_dup ( ZSTR_VAL ( ce - > name ) , ZSTR_LEN ( ce - > name ) ) ;
2009-06-19 03:29:47 +00:00
/* Only change the method to the constructor if the constructor isn't called __construct
* we check for __ so we can be binary safe for lowering , we should use ZEND_CONSTRUCTOR_FUNC_NAME
*/
2015-06-30 10:59:27 +00:00
if ( ! memcmp ( lc_class_name , ZSTR_VAL ( lc_function_name ) , ZSTR_LEN ( function_name ) ) & & memcmp ( ZSTR_VAL ( ce - > constructor - > common . function_name ) , " __ " , sizeof ( " __ " ) - 1 ) ) {
2008-03-17 14:54:42 +00:00
fbc = ce - > constructor ;
}
efree ( lc_class_name ) ;
}
2008-06-03 18:11:12 +00:00
2014-02-10 06:04:30 +00:00
if ( EXPECTED ( ! fbc ) ) {
zval * func = zend_hash_find ( & ce - > function_table , lc_function_name ) ;
if ( EXPECTED ( func ! = NULL ) ) {
fbc = Z_FUNC_P ( func ) ;
2007-09-29 08:52:40 +00:00
} else {
2014-02-10 06:04:30 +00:00
if ( UNEXPECTED ( ! key ) ) {
2014-12-24 12:04:51 +00:00
zend_string_release ( lc_function_name ) ;
2014-02-10 06:04:30 +00:00
}
if ( ce - > __call & &
2015-04-23 09:16:37 +00:00
( object = zend_get_this_object ( EG ( current_execute_data ) ) ) ! = NULL & &
instanceof_function ( object - > ce , ce ) ) {
2015-04-10 20:01:00 +00:00
/* Call the top-level defined __call().
* see : tests / classes / __call_004 . phpt */
2015-04-23 09:16:37 +00:00
zend_class_entry * call_ce = object - > ce ;
2015-04-10 20:01:00 +00:00
while ( ! call_ce - > __call ) {
call_ce = call_ce - > parent ;
}
return zend_get_user_call_function ( call_ce , function_name ) ;
2014-02-10 06:04:30 +00:00
} else if ( ce - > __callstatic ) {
return zend_get_user_callstatic_function ( ce , function_name ) ;
} else {
return NULL ;
}
2003-03-11 23:19:45 +00:00
}
2003-02-02 16:17:25 +00:00
}
2007-11-02 19:40:39 +00:00
# if MBO_0
/* right now this function is used for non static method lookup too */
/* Is the function static */
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( ! ( fbc - > common . fn_flags & ZEND_ACC_STATIC ) ) ) {
2015-06-30 10:59:27 +00:00
zend_error_noreturn ( E_ERROR , " Cannot call non static method %s::%s() without object " , ZEND_FN_SCOPE_NAME ( fbc ) , ZSTR_VAL ( fbc - > common . function_name ) ) ;
2007-11-02 19:40:39 +00:00
}
2012-05-13 05:12:48 +00:00
# endif
2003-02-02 16:17:25 +00:00
if ( fbc - > op_array . fn_flags & ZEND_ACC_PUBLIC ) {
/* No further checks necessary, most common case */
} else if ( fbc - > op_array . fn_flags & ZEND_ACC_PRIVATE ) {
zend_function * updated_fbc ;
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
2014-12-13 22:06:14 +00:00
updated_fbc = zend_check_private_int ( fbc , EG ( scope ) , lc_function_name ) ;
2010-05-06 12:52:27 +00:00
if ( EXPECTED ( updated_fbc ! = NULL ) ) {
2009-06-12 01:05:25 +00:00
fbc = updated_fbc ;
} else {
if ( ce - > __callstatic ) {
2014-02-10 06:04:30 +00:00
fbc = zend_get_user_callstatic_function ( ce , function_name ) ;
2010-04-20 10:57:45 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Call to %s method %s::%s() from context '%s' " , zend_visibility_string ( fbc - > common . fn_flags ) , ZEND_FN_SCOPE_NAME ( fbc ) , ZSTR_VAL ( function_name ) , EG ( scope ) ? ZSTR_VAL ( EG ( scope ) - > name ) : " " ) ;
2015-03-31 21:37:59 +00:00
fbc = NULL ;
2009-06-12 01:05:25 +00:00
}
2003-02-02 16:17:25 +00:00
}
} else if ( ( fbc - > common . fn_flags & ZEND_ACC_PROTECTED ) ) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( ! zend_check_protected ( zend_get_function_root_class ( fbc ) , EG ( scope ) ) ) ) {
2009-06-12 01:05:25 +00:00
if ( ce - > __callstatic ) {
2014-02-10 06:04:30 +00:00
fbc = zend_get_user_callstatic_function ( ce , function_name ) ;
2010-04-20 10:57:45 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Call to %s method %s::%s() from context '%s' " , zend_visibility_string ( fbc - > common . fn_flags ) , ZEND_FN_SCOPE_NAME ( fbc ) , ZSTR_VAL ( function_name ) , EG ( scope ) ? ZSTR_VAL ( EG ( scope ) - > name ) : " " ) ;
2015-03-31 21:37:59 +00:00
fbc = NULL ;
2009-06-12 01:05:25 +00:00
}
2003-02-02 16:17:25 +00:00
}
}
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( ! key ) ) {
2014-12-24 12:04:51 +00:00
zend_string_release ( lc_function_name ) ;
2010-04-20 10:57:45 +00:00
}
2003-02-02 16:17:25 +00:00
return fbc ;
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-02-02 16:17:25 +00:00
2015-01-13 06:33:15 +00:00
ZEND_API zval * zend_std_get_static_property ( zend_class_entry * ce , zend_string * property_name , zend_bool silent ) /* { { { */
2003-02-05 13:35:52 +00:00
{
2015-01-13 06:33:15 +00:00
zend_property_info * property_info = zend_hash_find_ptr ( & ce - > properties_info , property_name ) ;
2015-01-13 00:32:51 +00:00
zval * ret ;
2012-05-13 05:12:48 +00:00
2015-01-13 06:33:15 +00:00
if ( UNEXPECTED ( property_info = = NULL ) ) {
goto undeclared_property ;
}
2003-02-05 13:35:52 +00:00
2015-01-13 06:33:15 +00:00
if ( UNEXPECTED ( ! zend_verify_property_access ( property_info , ce ) ) ) {
if ( ! silent ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Cannot access %s property %s::$%s " , zend_visibility_string ( property_info - > flags ) , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( property_name ) ) ;
2010-05-24 14:11:39 +00:00
}
2015-01-13 06:33:15 +00:00
return NULL ;
}
2005-09-01 10:05:32 +00:00
2015-01-13 06:33:15 +00:00
if ( UNEXPECTED ( ( property_info - > flags & ZEND_ACC_STATIC ) = = 0 ) ) {
goto undeclared_property ;
}
2003-02-05 13:35:52 +00:00
2015-05-21 01:13:10 +00:00
if ( UNEXPECTED ( ! ( ce - > ce_flags & ZEND_ACC_CONSTANTS_UPDATED ) ) ) {
if ( UNEXPECTED ( zend_update_class_constants ( ce ) ) ! = SUCCESS ) {
return NULL ;
}
2015-04-01 23:05:25 +00:00
}
2015-01-13 06:33:15 +00:00
ret = CE_STATIC_MEMBERS ( ce ) + property_info - > offset ;
2006-05-09 23:53:23 +00:00
2015-01-13 06:33:15 +00:00
/* check if static properties were destoyed */
if ( UNEXPECTED ( CE_STATIC_MEMBERS ( ce ) = = NULL ) ) {
2015-01-13 00:32:51 +00:00
undeclared_property :
2015-01-13 06:33:15 +00:00
if ( ! silent ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Access to undeclared static property: %s::$%s " , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( property_name ) ) ;
2013-05-21 05:58:11 +00:00
}
2015-01-13 06:33:15 +00:00
ret = NULL ;
2013-05-21 05:58:11 +00:00
}
2015-01-03 09:22:58 +00:00
2015-01-13 00:32:51 +00:00
return ret ;
2003-02-05 13:35:52 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-02-05 13:35:52 +00:00
2015-08-19 11:40:56 +00:00
ZEND_API ZEND_COLD zend_bool zend_std_unset_static_property ( zend_class_entry * ce , zend_string * property_name ) /* { { { */
2003-02-17 14:06:39 +00:00
{
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Attempt to unset static property %s::$%s " , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( property_name ) ) ;
2003-02-17 14:06:39 +00:00
return 0 ;
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-02-17 14:06:39 +00:00
2014-12-13 22:06:14 +00:00
ZEND_API union _zend_function * zend_std_get_constructor ( zend_object * zobj ) /* { { { */
2002-02-07 14:08:43 +00:00
{
2003-02-02 16:17:25 +00:00
zend_function * constructor = zobj - > ce - > constructor ;
if ( constructor ) {
if ( constructor - > op_array . fn_flags & ZEND_ACC_PUBLIC ) {
/* No further checks necessary */
} else if ( constructor - > op_array . fn_flags & ZEND_ACC_PRIVATE ) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( constructor - > common . scope ! = EG ( scope ) ) ) {
2006-07-05 11:39:00 +00:00
if ( EG ( scope ) ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Call to private %s::%s() from context '%s' " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) , ZSTR_VAL ( EG ( scope ) - > name ) ) ;
2015-03-31 21:37:59 +00:00
constructor = NULL ;
2006-07-05 11:39:00 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Call to private %s::%s() from invalid context " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) ) ;
2015-03-31 21:37:59 +00:00
constructor = NULL ;
2006-07-05 11:39:00 +00:00
}
2003-02-02 16:17:25 +00:00
}
} else if ( ( constructor - > common . fn_flags & ZEND_ACC_PROTECTED ) ) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
2007-11-02 19:40:39 +00:00
* Constructors only have prototype if they are defined by an interface but
* it is the compilers responsibility to take care of the prototype .
2003-02-02 16:17:25 +00:00
*/
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( ! zend_check_protected ( zend_get_function_root_class ( constructor ) , EG ( scope ) ) ) ) {
2006-07-05 11:39:00 +00:00
if ( EG ( scope ) ) {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Call to protected %s::%s() from context '%s' " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) , ZSTR_VAL ( EG ( scope ) - > name ) ) ;
2015-03-31 21:37:59 +00:00
constructor = NULL ;
2006-07-05 11:39:00 +00:00
} else {
2015-07-07 17:10:22 +00:00
zend_throw_error ( NULL , " Call to protected %s::%s() from invalid context " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) ) ;
2015-03-31 21:37:59 +00:00
constructor = NULL ;
2006-07-05 11:39:00 +00:00
}
2003-02-02 16:17:25 +00:00
}
}
}
return constructor ;
2002-02-07 14:08:43 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-02-05 14:27:30 +00:00
2014-12-13 22:06:14 +00:00
static int zend_std_compare_objects ( zval * o1 , zval * o2 ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj1 , * zobj2 ;
2006-05-09 23:53:23 +00:00
2002-04-22 14:22:27 +00:00
zobj1 = Z_OBJ_P ( o1 ) ;
zobj2 = Z_OBJ_P ( o2 ) ;
2002-02-07 14:08:43 +00:00
2002-09-15 07:45:26 +00:00
if ( zobj1 - > ce ! = zobj2 - > ce ) {
2002-02-07 14:08:43 +00:00
return 1 ; /* different classes */
}
2010-05-24 14:11:39 +00:00
if ( ! zobj1 - > properties & & ! zobj2 - > properties ) {
2015-04-28 16:11:45 +00:00
zval * p1 , * p2 , * end ;
2013-01-09 07:30:50 +00:00
2015-04-28 16:11:45 +00:00
if ( ! zobj1 - > ce - > default_properties_count ) {
return 0 ;
}
p1 = zobj1 - > properties_table ;
p2 = zobj2 - > properties_table ;
end = p1 + zobj1 - > ce - > default_properties_count ;
2014-02-12 14:08:11 +00:00
Z_OBJ_PROTECT_RECURSION ( o1 ) ;
Z_OBJ_PROTECT_RECURSION ( o2 ) ;
2015-04-28 16:11:45 +00:00
do {
if ( Z_TYPE_P ( p1 ) ! = IS_UNDEF ) {
if ( Z_TYPE_P ( p2 ) ! = IS_UNDEF ) {
2010-05-24 14:11:39 +00:00
zval result ;
2014-12-13 22:06:14 +00:00
if ( compare_function ( & result , p1 , p2 ) = = FAILURE ) {
2014-02-12 14:08:11 +00:00
Z_OBJ_UNPROTECT_RECURSION ( o1 ) ;
Z_OBJ_UNPROTECT_RECURSION ( o2 ) ;
2010-05-24 14:11:39 +00:00
return 1 ;
}
2014-08-25 17:24:55 +00:00
if ( Z_LVAL ( result ) ! = 0 ) {
2014-02-12 14:08:11 +00:00
Z_OBJ_UNPROTECT_RECURSION ( o1 ) ;
Z_OBJ_UNPROTECT_RECURSION ( o2 ) ;
2014-08-25 17:24:55 +00:00
return Z_LVAL ( result ) ;
2010-05-24 14:11:39 +00:00
}
} else {
2014-02-12 14:08:11 +00:00
Z_OBJ_UNPROTECT_RECURSION ( o1 ) ;
Z_OBJ_UNPROTECT_RECURSION ( o2 ) ;
2010-05-24 14:11:39 +00:00
return 1 ;
}
} else {
2015-04-28 16:11:45 +00:00
if ( Z_TYPE_P ( p2 ) ! = IS_UNDEF ) {
2014-02-12 14:08:11 +00:00
Z_OBJ_UNPROTECT_RECURSION ( o1 ) ;
Z_OBJ_UNPROTECT_RECURSION ( o2 ) ;
2010-05-24 14:11:39 +00:00
return 1 ;
}
}
2015-04-28 16:11:45 +00:00
p1 + + ;
p2 + + ;
} while ( p1 ! = end ) ;
2014-02-12 14:08:11 +00:00
Z_OBJ_UNPROTECT_RECURSION ( o1 ) ;
Z_OBJ_UNPROTECT_RECURSION ( o2 ) ;
2010-05-24 14:11:39 +00:00
return 0 ;
} else {
if ( ! zobj1 - > properties ) {
rebuild_object_properties ( zobj1 ) ;
}
if ( ! zobj2 - > properties ) {
rebuild_object_properties ( zobj2 ) ;
}
2014-12-22 04:16:25 +00:00
return zend_compare_symbol_tables ( zobj1 - > properties , zobj2 - > properties ) ;
2010-05-24 14:11:39 +00:00
}
2002-02-07 14:08:43 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2014-12-13 22:06:14 +00:00
static int zend_std_has_property ( zval * object , zval * member , int has_set_exists , void * * cache_slot ) /* { { { */
2002-02-07 14:08:43 +00:00
{
zend_object * zobj ;
int result ;
2014-02-10 06:04:30 +00:00
zval * value = NULL ;
zval tmp_member ;
2015-01-13 08:33:00 +00:00
uint32_t property_offset ;
2006-05-09 23:53:23 +00:00
2003-02-05 14:27:30 +00:00
zobj = Z_OBJ_P ( object ) ;
2014-02-10 06:04:30 +00:00
ZVAL_UNDEF ( & tmp_member ) ;
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( Z_TYPE_P ( member ) ! = IS_STRING ) ) {
2014-10-06 16:45:08 +00:00
ZVAL_STR ( & tmp_member , zval_get_string ( member ) ) ;
2014-02-10 06:04:30 +00:00
member = & tmp_member ;
2014-07-07 16:54:31 +00:00
cache_slot = NULL ;
2002-02-07 14:08:43 +00:00
}
2003-02-05 14:27:30 +00:00
2015-01-13 08:33:00 +00:00
property_offset = zend_get_property_offset ( zobj - > ce , Z_STR_P ( member ) , 1 , cache_slot ) ;
2005-07-07 16:07:09 +00:00
2015-01-13 08:33:00 +00:00
if ( EXPECTED ( property_offset ! = ZEND_WRONG_PROPERTY_OFFSET ) ) {
if ( EXPECTED ( property_offset ! = ZEND_DYNAMIC_PROPERTY_OFFSET ) ) {
value = OBJ_PROP ( zobj , property_offset ) ;
2014-03-26 14:07:31 +00:00
if ( Z_TYPE_P ( value ) ! = IS_UNDEF ) {
goto found ;
2014-02-21 18:59:51 +00:00
}
2014-10-20 16:33:35 +00:00
} else if ( EXPECTED ( zobj - > properties ! = NULL ) & &
2014-10-17 15:10:05 +00:00
( value = zend_hash_find ( zobj - > properties , Z_STR_P ( member ) ) ) ! = NULL ) {
2014-02-10 06:04:30 +00:00
found :
2014-03-26 14:07:31 +00:00
switch ( has_set_exists ) {
case 0 :
2014-08-14 17:54:57 +00:00
ZVAL_DEREF ( value ) ;
2014-03-26 14:07:31 +00:00
result = ( Z_TYPE_P ( value ) ! = IS_NULL ) ;
break ;
default :
2014-12-13 22:06:14 +00:00
result = zend_is_true ( value ) ;
2014-03-26 14:07:31 +00:00
break ;
case 2 :
result = 1 ;
break ;
2014-02-10 06:04:30 +00:00
}
2014-03-26 14:07:31 +00:00
goto exit ;
2014-02-10 06:04:30 +00:00
}
2015-03-31 21:37:59 +00:00
} else if ( UNEXPECTED ( EG ( exception ) ) ) {
result = 0 ;
goto exit ;
2014-02-10 06:04:30 +00:00
}
result = 0 ;
if ( ( has_set_exists ! = 2 ) & & zobj - > ce - > __isset ) {
2014-10-17 15:10:05 +00:00
zend_long * guard = zend_get_property_guard ( zobj , Z_STR_P ( member ) ) ;
2014-02-10 06:04:30 +00:00
if ( ! ( ( * guard ) & IN_ISSET ) ) {
zval rv ;
2014-04-16 14:06:03 +00:00
zval tmp_object ;
2003-02-05 14:27:30 +00:00
2005-07-07 16:07:09 +00:00
/* have issetter - try with it! */
2014-04-16 14:06:03 +00:00
ZVAL_COPY ( & tmp_object , object ) ;
2014-02-10 06:04:30 +00:00
( * guard ) | = IN_ISSET ; /* prevent circular getting */
2014-12-13 22:06:14 +00:00
zend_std_call_issetter ( & tmp_object , member , & rv ) ;
2014-02-10 06:04:30 +00:00
if ( Z_TYPE ( rv ) ! = IS_UNDEF ) {
2014-12-13 22:06:14 +00:00
result = zend_is_true ( & rv ) ;
2005-07-07 16:07:09 +00:00
zval_ptr_dtor ( & rv ) ;
2008-05-03 00:38:55 +00:00
if ( has_set_exists & & result ) {
2014-02-10 06:04:30 +00:00
if ( EXPECTED ( ! EG ( exception ) ) & & zobj - > ce - > __get & & ! ( ( * guard ) & IN_GET ) ) {
( * guard ) | = IN_GET ;
2014-12-13 22:06:14 +00:00
zend_std_call_getter ( & tmp_object , member , & rv ) ;
2014-02-10 06:04:30 +00:00
( * guard ) & = ~ IN_GET ;
if ( Z_TYPE ( rv ) ! = IS_UNDEF ) {
2014-12-13 22:06:14 +00:00
result = i_zend_is_true ( & rv ) ;
2008-05-03 00:38:55 +00:00
zval_ptr_dtor ( & rv ) ;
} else {
result = 0 ;
}
} else {
result = 0 ;
2005-07-07 16:07:09 +00:00
}
}
}
2014-02-10 06:04:30 +00:00
( * guard ) & = ~ IN_ISSET ;
2014-04-16 14:06:03 +00:00
zval_ptr_dtor ( & tmp_object ) ;
2002-02-07 14:08:43 +00:00
}
}
2014-02-10 06:04:30 +00:00
exit :
2015-09-10 06:57:22 +00:00
if ( UNEXPECTED ( Z_REFCOUNTED ( tmp_member ) ) ) {
2005-07-07 16:07:09 +00:00
zval_ptr_dtor ( & tmp_member ) ;
2002-02-07 14:08:43 +00:00
}
return result ;
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-02-07 14:08:43 +00:00
2014-12-13 22:06:14 +00:00
zend_string * zend_std_object_get_class_name ( const zend_object * zobj ) /* { { { */
2003-01-12 13:56:51 +00:00
{
2014-10-09 17:15:07 +00:00
return zend_string_copy ( zobj - > ce - > name ) ;
2003-01-12 13:56:51 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-01-12 13:56:51 +00:00
2014-12-13 22:06:14 +00:00
ZEND_API int zend_std_cast_object_tostring ( zval * readobj , zval * writeobj , int type ) /* { { { */
2003-12-15 16:59:21 +00:00
{
2014-02-10 06:04:30 +00:00
zval retval ;
2006-05-09 23:53:23 +00:00
zend_class_entry * ce ;
2003-12-15 16:59:21 +00:00
switch ( type ) {
case IS_STRING :
2006-05-09 23:53:23 +00:00
ce = Z_OBJCE_P ( readobj ) ;
if ( ce - > __tostring & &
2014-02-10 06:04:30 +00:00
( zend_call_method_with_0_params ( readobj , ce , & ce - > __tostring , " __tostring " , & retval ) | | EG ( exception ) ) ) {
2010-05-06 12:52:27 +00:00
if ( UNEXPECTED ( EG ( exception ) ! = NULL ) ) {
2015-11-29 07:38:19 +00:00
zval * msg , ex , rv ;
2014-02-24 09:49:53 +00:00
zval_ptr_dtor ( & retval ) ;
2015-11-29 07:38:19 +00:00
ZVAL_OBJ ( & ex , EG ( exception ) ) ;
2012-09-06 07:26:40 +00:00
EG ( exception ) = NULL ;
2015-11-29 07:38:19 +00:00
msg = zend_read_property ( Z_OBJCE ( ex ) , & ex , " message " , sizeof ( " message " ) - 1 , 1 , & rv ) ;
if ( UNEXPECTED ( Z_TYPE_P ( msg ) ! = IS_STRING ) ) {
ZVAL_EMPTY_STRING ( & rv ) ;
msg = & rv ;
}
zend_error_noreturn ( E_ERROR ,
" Method %s::__toString() must not throw an exception, caught %s: %s " ,
ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( Z_OBJCE ( ex ) - > name ) , Z_STRVAL_P ( msg ) ) ;
2007-10-18 20:44:41 +00:00
return FAILURE ;
}
2014-02-10 06:04:30 +00:00
if ( EXPECTED ( Z_TYPE ( retval ) = = IS_STRING ) ) {
2007-12-21 20:56:33 +00:00
if ( readobj = = writeobj ) {
2014-02-21 08:56:23 +00:00
zval_ptr_dtor ( readobj ) ;
2007-12-21 20:56:33 +00:00
}
2014-02-21 08:56:23 +00:00
ZVAL_COPY_VALUE ( writeobj , & retval ) ;
2006-05-09 23:53:23 +00:00
return SUCCESS ;
2003-12-15 16:59:21 +00:00
} else {
2006-05-09 23:53:23 +00:00
zval_ptr_dtor ( & retval ) ;
2007-12-21 20:56:33 +00:00
if ( readobj = = writeobj ) {
2014-02-21 08:56:23 +00:00
zval_ptr_dtor ( readobj ) ;
2007-12-21 20:56:33 +00:00
}
2006-05-09 23:53:23 +00:00
ZVAL_EMPTY_STRING ( writeobj ) ;
2015-06-30 10:59:27 +00:00
zend_error ( E_RECOVERABLE_ERROR , " Method %s::__toString() must return a string value " , ZSTR_VAL ( ce - > name ) ) ;
2006-05-09 23:53:23 +00:00
return SUCCESS ;
2003-12-15 16:59:21 +00:00
}
}
2006-05-09 23:53:23 +00:00
return FAILURE ;
2014-04-30 14:32:42 +00:00
case _IS_BOOL :
2006-05-09 23:53:23 +00:00
ZVAL_BOOL ( writeobj , 1 ) ;
return SUCCESS ;
2014-08-25 17:24:55 +00:00
case IS_LONG :
2006-05-09 23:53:23 +00:00
ce = Z_OBJCE_P ( readobj ) ;
2015-06-30 10:59:27 +00:00
zend_error ( E_NOTICE , " Object of class %s could not be converted to int " , ZSTR_VAL ( ce - > name ) ) ;
2007-12-21 20:56:33 +00:00
if ( readobj = = writeobj ) {
zval_dtor ( readobj ) ;
}
2014-08-25 17:24:55 +00:00
ZVAL_LONG ( writeobj , 1 ) ;
2006-05-09 23:53:23 +00:00
return SUCCESS ;
case IS_DOUBLE :
ce = Z_OBJCE_P ( readobj ) ;
2015-06-30 10:59:27 +00:00
zend_error ( E_NOTICE , " Object of class %s could not be converted to float " , ZSTR_VAL ( ce - > name ) ) ;
2007-12-21 20:56:33 +00:00
if ( readobj = = writeobj ) {
zval_dtor ( readobj ) ;
}
2006-05-09 23:53:23 +00:00
ZVAL_DOUBLE ( writeobj , 1 ) ;
return SUCCESS ;
2003-12-15 16:59:21 +00:00
default :
2014-02-10 06:04:30 +00:00
ZVAL_NULL ( writeobj ) ;
2003-12-15 16:59:21 +00:00
break ;
}
return FAILURE ;
}
2007-11-02 19:40:39 +00:00
/* }}} */
2003-09-18 11:38:33 +00:00
2014-12-13 22:06:14 +00:00
int zend_std_get_closure ( zval * obj , zend_class_entry * * ce_ptr , zend_function * * fptr_ptr , zend_object * * obj_ptr ) /* { { { */
2008-08-14 21:36:56 +00:00
{
2014-02-10 06:04:30 +00:00
zval * func ;
2008-08-14 21:36:56 +00:00
zend_class_entry * ce ;
2014-02-10 06:04:30 +00:00
2008-08-14 21:36:56 +00:00
if ( Z_TYPE_P ( obj ) ! = IS_OBJECT ) {
return FAILURE ;
}
ce = Z_OBJCE_P ( obj ) ;
2014-02-10 06:04:30 +00:00
if ( ( func = zend_hash_str_find ( & ce - > function_table , ZEND_INVOKE_FUNC_NAME , sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) ) = = NULL ) {
2008-08-14 21:36:56 +00:00
return FAILURE ;
}
2014-02-10 06:04:30 +00:00
* fptr_ptr = Z_FUNC_P ( func ) ;
2008-08-14 21:36:56 +00:00
* ce_ptr = ce ;
if ( ( * fptr_ptr ) - > common . fn_flags & ZEND_ACC_STATIC ) {
2014-03-27 22:11:22 +00:00
if ( obj_ptr ) {
* obj_ptr = NULL ;
2008-08-14 21:36:56 +00:00
}
} else {
2014-03-27 22:11:22 +00:00
if ( obj_ptr ) {
* obj_ptr = Z_OBJ_P ( obj ) ;
2008-08-14 21:36:56 +00:00
}
}
return SUCCESS ;
}
/* }}} */
2003-12-22 13:09:15 +00:00
ZEND_API zend_object_handlers std_object_handlers = {
2014-04-08 21:50:15 +00:00
0 , /* offset */
zend_object_std_dtor , /* free_obj */
2014-02-21 11:48:56 +00:00
zend_objects_destroy_object , /* dtor_obj */
2003-07-07 09:12:15 +00:00
zend_objects_clone_obj , /* clone_obj */
2006-05-09 23:53:23 +00:00
2003-07-07 09:12:15 +00:00
zend_std_read_property , /* read_property */
zend_std_write_property , /* write_property */
2003-07-07 10:53:27 +00:00
zend_std_read_dimension , /* read_dimension */
2003-07-07 09:12:15 +00:00
zend_std_write_dimension , /* write_dimension */
2003-10-05 07:52:28 +00:00
zend_std_get_property_ptr_ptr , /* get_property_ptr_ptr */
2003-07-07 09:12:15 +00:00
NULL , /* get */
NULL , /* set */
zend_std_has_property , /* has_property */
zend_std_unset_property , /* unset_property */
2003-11-10 16:14:44 +00:00
zend_std_has_dimension , /* has_dimension */
2003-07-30 17:12:06 +00:00
zend_std_unset_dimension , /* unset_dimension */
2003-07-07 09:12:15 +00:00
zend_std_get_properties , /* get_properties */
zend_std_get_method , /* get_method */
NULL , /* call_method */
zend_std_get_constructor , /* get_constructor */
zend_std_object_get_class_name , /* get_class_name */
zend_std_compare_objects , /* compare_objects */
2006-05-09 23:53:23 +00:00
zend_std_cast_object_tostring , /* cast_object */
2004-05-04 15:03:28 +00:00
NULL , /* count_elements */
2014-02-18 03:13:00 +00:00
zend_std_get_debug_info , /* get_debug_info */
2008-08-14 21:36:56 +00:00
zend_std_get_closure , /* get_closure */
2011-11-02 06:31:33 +00:00
zend_std_get_gc , /* get_gc */
2013-06-17 15:48:13 +00:00
NULL , /* do_operation */
NULL , /* compare */
2002-02-07 14:08:43 +00:00
} ;
2003-02-01 01:49:15 +00:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* indent - tabs - mode : t
* End :
*/