1999-04-17 00:37:12 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2019-01-30 09:03:12 +00:00
| Copyright ( c ) The PHP Group |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 12:51:34 +00:00
| This source file is subject to version 3.01 of the PHP license , |
1999-07-16 13:13:16 +00:00
| 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 : |
2021-05-06 10:16:35 +00:00
| https : //www.php.net/license/3_01.txt |
1999-07-16 13:13:16 +00:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2011-10-19 10:09:24 +00:00
| Authors : Jani Lehtimäki < jkl @ njet . net > |
2000-10-29 09:14:55 +00:00
| Thies C . Arntzen < thies @ thieso . net > |
2000-06-23 16:21:31 +00:00
| Sascha Schumann < sascha @ schumann . cx > |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2000-12-11 12:52:52 +00:00
*/
1999-04-17 00:37:12 +00:00
2020-07-01 13:32:55 +00:00
/* {{{ includes */
1999-04-17 00:37:12 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>
# include "php.h"
1999-12-04 19:19:57 +00:00
# include "php_string.h"
# include "php_var.h"
2014-09-20 20:42:02 +00:00
# include "zend_smart_str.h"
2000-06-23 16:21:31 +00:00
# include "basic_functions.h"
2000-06-23 16:46:04 +00:00
# include "php_incomplete_class.h"
2020-06-10 21:10:18 +00:00
# include "zend_enum.h"
2015-09-03 22:17:44 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2016-08-10 10:51:48 +00:00
struct php_serialize_data {
HashTable ht ;
uint32_t n ;
} ;
2014-02-21 18:59:51 +00:00
# define COMMON (is_ref ? "&" : "")
2015-09-03 22:17:44 +00:00
2014-12-13 22:06:14 +00:00
static void php_array_element_dump ( zval * zv , zend_ulong index , zend_string * key , int level ) /* { { { */
2000-06-09 15:13:36 +00:00
{
2014-05-27 22:13:45 +00:00
if ( key = = NULL ) { /* numeric key */
2014-08-25 18:22:49 +00:00
php_printf ( " %*c[ " ZEND_LONG_FMT " ]=> \n " , level + 1 , ' ' , index ) ;
2000-06-09 15:13:36 +00:00
} else { /* string key */
2003-11-29 04:43:06 +00:00
php_printf ( " %*c[ \" " , level + 1 , ' ' ) ;
2015-06-30 01:05:24 +00:00
PHPWRITE ( ZSTR_VAL ( key ) , ZSTR_LEN ( key ) ) ;
2003-11-29 04:43:06 +00:00
php_printf ( " \" ]=> \n " ) ;
2015-04-15 19:07:34 +00:00
}
2014-12-13 22:06:14 +00:00
php_var_dump ( zv , level + 2 ) ;
2000-06-09 15:13:36 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2000-06-09 15:13:36 +00:00
2019-01-07 11:28:51 +00:00
static void php_object_property_dump ( zend_property_info * prop_info , zval * zv , zend_ulong index , zend_string * key , int level ) /* { { { */
2004-05-20 17:46:20 +00:00
{
2011-09-13 13:29:35 +00:00
const char * prop_name , * class_name ;
2004-05-20 17:46:20 +00:00
2014-05-27 22:13:45 +00:00
if ( key = = NULL ) { /* numeric key */
2014-08-25 18:22:49 +00:00
php_printf ( " %*c[ " ZEND_LONG_FMT " ]=> \n " , level + 1 , ' ' , index ) ;
2004-05-20 17:46:20 +00:00
} else { /* string key */
2014-09-15 22:23:58 +00:00
int unmangle = zend_unmangle_property_name ( key , & class_name , & prop_name ) ;
2007-11-02 19:40:39 +00:00
php_printf ( " %*c[ " , level + 1 , ' ' ) ;
2006-07-24 23:40:57 +00:00
if ( class_name & & unmangle = = SUCCESS ) {
2007-11-02 19:40:39 +00:00
if ( class_name [ 0 ] = = ' * ' ) {
php_printf ( " \" %s \" :protected " , prop_name ) ;
2004-05-20 17:46:20 +00:00
} else {
2007-11-02 19:40:39 +00:00
php_printf ( " \" %s \" : \" %s \" :private " , prop_name , class_name ) ;
2004-05-20 17:46:20 +00:00
}
} else {
2007-11-02 19:40:39 +00:00
php_printf ( " \" " ) ;
2015-06-30 01:05:24 +00:00
PHPWRITE ( ZSTR_VAL ( key ) , ZSTR_LEN ( key ) ) ;
2007-11-02 19:40:39 +00:00
php_printf ( " \" " ) ;
2004-05-20 17:46:20 +00:00
}
2007-11-02 19:40:39 +00:00
ZEND_PUTS ( " ]=> \n " ) ;
2004-05-20 17:46:20 +00:00
}
2019-01-07 11:28:51 +00:00
if ( Z_TYPE_P ( zv ) = = IS_UNDEF ) {
2019-09-23 14:53:54 +00:00
ZEND_ASSERT ( ZEND_TYPE_IS_SET ( prop_info - > type ) ) ;
2019-09-19 10:11:29 +00:00
zend_string * type_str = zend_type_to_string ( prop_info - > type ) ;
php_printf ( " %*cuninitialized(%s) \n " ,
level + 1 , ' ' , ZSTR_VAL ( type_str ) ) ;
zend_string_release ( type_str ) ;
2019-01-07 11:28:51 +00:00
} else {
php_var_dump ( zv , level + 2 ) ;
}
2004-05-20 17:46:20 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2004-05-20 17:46:20 +00:00
2014-12-13 22:06:14 +00:00
PHPAPI void php_var_dump ( zval * struc , int level ) /* { { { */
1999-04-17 00:37:12 +00:00
{
2007-11-02 19:40:39 +00:00
HashTable * myht ;
2014-02-13 13:54:23 +00:00
zend_string * class_name ;
2014-02-21 18:59:51 +00:00
int is_ref = 0 ;
2014-08-25 17:24:55 +00:00
zend_ulong num ;
2014-05-27 22:13:45 +00:00
zend_string * key ;
zval * val ;
2015-09-01 07:39:00 +00:00
uint32_t count ;
1999-04-17 00:37:12 +00:00
2001-08-17 07:50:15 +00:00
if ( level > 1 ) {
php_printf ( " %*c " , level - 1 , ' ' ) ;
2000-06-09 15:13:36 +00:00
}
2014-03-09 12:03:24 +00:00
again :
2014-02-13 13:54:23 +00:00
switch ( Z_TYPE_P ( struc ) ) {
2014-04-30 14:32:42 +00:00
case IS_FALSE :
php_printf ( " %sbool(false) \n " , COMMON ) ;
break ;
case IS_TRUE :
php_printf ( " %sbool(true) \n " , COMMON ) ;
2014-03-09 12:03:24 +00:00
break ;
case IS_NULL :
php_printf ( " %sNULL \n " , COMMON ) ;
break ;
2014-08-25 17:24:55 +00:00
case IS_LONG :
2014-08-25 18:22:49 +00:00
php_printf ( " %sint( " ZEND_LONG_FMT " ) \n " , COMMON , Z_LVAL_P ( struc ) ) ;
2014-03-09 12:03:24 +00:00
break ;
case IS_DOUBLE :
2020-02-29 21:47:04 +00:00
php_printf_unchecked ( " %sfloat(%.*H) \n " , COMMON , ( int ) PG ( serialize_precision ) , Z_DVAL_P ( struc ) ) ;
2014-03-09 12:03:24 +00:00
break ;
case IS_STRING :
2016-02-14 13:02:19 +00:00
php_printf ( " %sstring(%zd) \" " , COMMON , Z_STRLEN_P ( struc ) ) ;
2014-08-25 17:24:55 +00:00
PHPWRITE ( Z_STRVAL_P ( struc ) , Z_STRLEN_P ( struc ) ) ;
2014-03-09 12:03:24 +00:00
PUTS ( " \" \n " ) ;
break ;
case IS_ARRAY :
myht = Z_ARRVAL_P ( struc ) ;
2020-02-12 09:27:28 +00:00
if ( ! ( GC_FLAGS ( myht ) & GC_IMMUTABLE ) ) {
2017-10-05 22:34:50 +00:00
if ( GC_IS_RECURSIVE ( myht ) ) {
PUTS ( " *RECURSION* \n " ) ;
return ;
}
2020-07-10 22:14:22 +00:00
GC_ADDREF ( myht ) ;
2017-10-05 22:34:50 +00:00
GC_PROTECT_RECURSION ( myht ) ;
2014-03-09 12:03:24 +00:00
}
2020-12-03 15:58:03 +00:00
count = zend_hash_num_elements ( myht ) ;
2015-09-01 07:39:00 +00:00
php_printf ( " %sarray(%d) { \n " , COMMON , count ) ;
2020-12-03 15:58:03 +00:00
ZEND_HASH_FOREACH_KEY_VAL ( myht , num , key , val ) {
2014-12-13 22:06:14 +00:00
php_array_element_dump ( val , num , key , level ) ;
2014-05-27 22:13:45 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2020-02-12 09:27:28 +00:00
if ( ! ( GC_FLAGS ( myht ) & GC_IMMUTABLE ) ) {
2017-10-05 22:34:50 +00:00
GC_UNPROTECT_RECURSION ( myht ) ;
2020-07-11 06:37:25 +00:00
GC_DELREF ( myht ) ;
2014-05-29 14:21:56 +00:00
}
2014-05-27 22:13:45 +00:00
if ( level > 1 ) {
php_printf ( " %*c " , level - 1 , ' ' ) ;
}
PUTS ( " } \n " ) ;
break ;
2020-06-10 21:10:18 +00:00
case IS_OBJECT : {
zend_class_entry * ce = Z_OBJCE_P ( struc ) ;
if ( ce - > ce_flags & ZEND_ACC_ENUM ) {
zval * case_name_zval = zend_enum_fetch_case_name ( Z_OBJ_P ( struc ) ) ;
php_printf ( " %senum(%s::%s) \n " , COMMON , ZSTR_VAL ( ce - > name ) , Z_STRVAL_P ( case_name_zval ) ) ;
return ;
}
2017-10-05 22:34:50 +00:00
if ( Z_IS_RECURSIVE_P ( struc ) ) {
2014-03-09 12:03:24 +00:00
PUTS ( " *RECURSION* \n " ) ;
return ;
}
2017-10-05 22:34:50 +00:00
Z_PROTECT_RECURSION_P ( struc ) ;
2003-02-01 03:52:31 +00:00
2018-10-04 11:58:35 +00:00
myht = zend_get_properties_for ( struc , ZEND_PROP_PURPOSE_DEBUG ) ;
2014-12-13 22:06:14 +00:00
class_name = Z_OBJ_HANDLER_P ( struc , get_class_name ) ( Z_OBJ_P ( struc ) ) ;
2015-11-23 14:12:03 +00:00
php_printf ( " %sobject(%s)#%d (%d) { \n " , COMMON , ZSTR_VAL ( class_name ) , Z_OBJ_HANDLE_P ( struc ) , myht ? zend_array_count ( myht ) : 0 ) ;
2018-05-28 13:27:12 +00:00
zend_string_release_ex ( class_name , 0 ) ;
2014-10-09 17:15:07 +00:00
2014-03-09 12:03:24 +00:00
if ( myht ) {
2014-08-25 17:24:55 +00:00
zend_ulong num ;
2014-05-27 22:13:45 +00:00
zend_string * key ;
zval * val ;
2019-01-07 11:28:51 +00:00
ZEND_HASH_FOREACH_KEY_VAL ( myht , num , key , val ) {
zend_property_info * prop_info = NULL ;
if ( Z_TYPE_P ( val ) = = IS_INDIRECT ) {
val = Z_INDIRECT_P ( val ) ;
if ( key ) {
prop_info = zend_get_typed_property_info_for_slot ( Z_OBJ_P ( struc ) , val ) ;
}
}
if ( ! Z_ISUNDEF_P ( val ) | | prop_info ) {
php_object_property_dump ( prop_info , val , num , key , level ) ;
}
2014-05-27 22:13:45 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2018-10-04 11:58:35 +00:00
zend_release_properties ( myht ) ;
2014-03-09 12:03:24 +00:00
}
if ( level > 1 ) {
php_printf ( " %*c " , level - 1 , ' ' ) ;
}
PUTS ( " } \n " ) ;
2017-10-05 22:34:50 +00:00
Z_UNPROTECT_RECURSION_P ( struc ) ;
2014-03-09 12:03:24 +00:00
break ;
2020-06-10 21:10:18 +00:00
}
2014-03-09 12:03:24 +00:00
case IS_RESOURCE : {
2014-12-13 22:06:14 +00:00
const char * type_name = zend_rsrc_list_get_rsrc_type ( Z_RES_P ( struc ) ) ;
2016-06-21 13:00:37 +00:00
php_printf ( " %sresource(%d) of type (%s) \n " , COMMON , Z_RES_P ( struc ) - > handle , type_name ? type_name : " Unknown " ) ;
2014-03-09 12:03:24 +00:00
break ;
2003-02-01 03:52:31 +00:00
}
2014-03-09 12:03:24 +00:00
case IS_REFERENCE :
2014-04-15 17:56:30 +00:00
//??? hide references with refcount==1 (for compatibility)
2014-03-09 12:03:24 +00:00
if ( Z_REFCOUNT_P ( struc ) > 1 ) {
is_ref = 1 ;
}
struc = Z_REFVAL_P ( struc ) ;
goto again ;
break ;
default :
php_printf ( " %sUNKNOWN:0 \n " , COMMON ) ;
break ;
1999-04-17 00:37:12 +00:00
}
}
1999-04-25 12:41:18 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2020-07-01 13:32:55 +00:00
/* {{{ Dumps a string representation of variable to output */
1999-04-17 00:37:12 +00:00
PHP_FUNCTION ( var_dump )
{
2014-02-13 13:54:23 +00:00
zval * args ;
1999-09-20 14:14:26 +00:00
int argc ;
int i ;
2007-11-02 19:40:39 +00:00
2016-12-31 02:03:33 +00:00
ZEND_PARSE_PARAMETERS_START ( 1 , - 1 )
Z_PARAM_VARIADIC ( ' + ' , args , argc )
ZEND_PARSE_PARAMETERS_END ( ) ;
2007-11-02 19:40:39 +00:00
for ( i = 0 ; i < argc ; i + + ) {
2014-12-13 22:06:14 +00:00
php_var_dump ( & args [ i ] , 1 ) ;
2007-11-02 19:40:39 +00:00
}
1999-04-17 00:37:12 +00:00
}
1999-04-25 12:41:18 +00:00
/* }}} */
1999-09-20 14:14:26 +00:00
2014-12-13 22:06:14 +00:00
static void zval_array_element_dump ( zval * zv , zend_ulong index , zend_string * key , int level ) /* { { { */
2002-02-10 06:52:35 +00:00
{
2014-05-27 22:13:45 +00:00
if ( key = = NULL ) { /* numeric key */
2014-08-25 18:22:49 +00:00
php_printf ( " %*c[ " ZEND_LONG_FMT " ]=> \n " , level + 1 , ' ' , index ) ;
2002-02-10 06:52:35 +00:00
} else { /* string key */
2003-11-29 04:43:06 +00:00
php_printf ( " %*c[ \" " , level + 1 , ' ' ) ;
2015-06-30 01:05:24 +00:00
PHPWRITE ( ZSTR_VAL ( key ) , ZSTR_LEN ( key ) ) ;
2003-11-29 04:43:06 +00:00
php_printf ( " \" ]=> \n " ) ;
2002-02-10 06:52:35 +00:00
}
2014-12-13 22:06:14 +00:00
php_debug_zval_dump ( zv , level + 2 ) ;
2002-02-10 06:52:35 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-02-10 06:52:35 +00:00
2019-01-07 11:28:51 +00:00
static void zval_object_property_dump ( zend_property_info * prop_info , zval * zv , zend_ulong index , zend_string * key , int level ) /* { { { */
2006-03-10 08:42:56 +00:00
{
2011-09-13 13:29:35 +00:00
const char * prop_name , * class_name ;
2006-03-10 08:42:56 +00:00
2014-05-27 22:13:45 +00:00
if ( key = = NULL ) { /* numeric key */
2014-08-25 18:22:49 +00:00
php_printf ( " %*c[ " ZEND_LONG_FMT " ]=> \n " , level + 1 , ' ' , index ) ;
2006-03-10 08:42:56 +00:00
} else { /* string key */
2014-09-15 22:23:58 +00:00
zend_unmangle_property_name ( key , & class_name , & prop_name ) ;
2007-11-02 19:40:39 +00:00
php_printf ( " %*c[ " , level + 1 , ' ' ) ;
2006-03-10 08:42:56 +00:00
if ( class_name ) {
2007-11-02 19:40:39 +00:00
if ( class_name [ 0 ] = = ' * ' ) {
php_printf ( " \" %s \" :protected " , prop_name ) ;
2006-03-10 08:42:56 +00:00
} else {
2007-11-02 19:40:39 +00:00
php_printf ( " \" %s \" : \" %s \" :private " , prop_name , class_name ) ;
2006-03-10 08:42:56 +00:00
}
} else {
2007-11-02 19:40:39 +00:00
php_printf ( " \" %s \" " , prop_name ) ;
2006-03-10 08:42:56 +00:00
}
2007-11-02 19:40:39 +00:00
ZEND_PUTS ( " ]=> \n " ) ;
2006-03-10 08:42:56 +00:00
}
2019-01-07 11:28:51 +00:00
if ( prop_info & & Z_TYPE_P ( zv ) = = IS_UNDEF ) {
2019-09-19 10:11:29 +00:00
zend_string * type_str = zend_type_to_string ( prop_info - > type ) ;
php_printf ( " %*cuninitialized(%s) \n " ,
level + 1 , ' ' , ZSTR_VAL ( type_str ) ) ;
zend_string_release ( type_str ) ;
2019-01-07 11:28:51 +00:00
} else {
php_debug_zval_dump ( zv , level + 2 ) ;
}
2006-03-10 08:42:56 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2006-03-10 08:42:56 +00:00
2014-12-13 22:06:14 +00:00
PHPAPI void php_debug_zval_dump ( zval * struc , int level ) /* { { { */
2002-02-10 06:52:35 +00:00
{
2002-03-14 14:05:13 +00:00
HashTable * myht = NULL ;
2014-02-13 13:54:23 +00:00
zend_string * class_name ;
2014-08-25 17:24:55 +00:00
zend_ulong index ;
2014-05-27 22:13:45 +00:00
zend_string * key ;
zval * val ;
2015-09-01 07:39:00 +00:00
uint32_t count ;
2002-02-10 06:52:35 +00:00
if ( level > 1 ) {
php_printf ( " %*c " , level - 1 , ' ' ) ;
}
2014-02-13 13:54:23 +00:00
switch ( Z_TYPE_P ( struc ) ) {
2014-04-30 14:32:42 +00:00
case IS_FALSE :
2021-03-03 15:28:39 +00:00
PUTS ( " bool(false) \n " ) ;
2014-04-30 14:32:42 +00:00
break ;
case IS_TRUE :
2021-03-03 15:28:39 +00:00
PUTS ( " bool(true) \n " ) ;
2002-02-10 06:52:35 +00:00
break ;
case IS_NULL :
2021-03-03 15:28:39 +00:00
PUTS ( " NULL \n " ) ;
2002-02-10 06:52:35 +00:00
break ;
2014-08-25 17:24:55 +00:00
case IS_LONG :
2021-03-03 15:28:39 +00:00
php_printf ( " int( " ZEND_LONG_FMT " ) \n " , Z_LVAL_P ( struc ) ) ;
2002-02-10 06:52:35 +00:00
break ;
case IS_DOUBLE :
2021-03-03 15:28:39 +00:00
php_printf_unchecked ( " float(%.*H) \n " , ( int ) PG ( serialize_precision ) , Z_DVAL_P ( struc ) ) ;
2002-02-10 06:52:35 +00:00
break ;
case IS_STRING :
2021-03-03 15:28:39 +00:00
php_printf ( " string(%zd) \" " , Z_STRLEN_P ( struc ) ) ;
2014-08-25 17:24:55 +00:00
PHPWRITE ( Z_STRVAL_P ( struc ) , Z_STRLEN_P ( struc ) ) ;
2021-01-12 09:26:17 +00:00
if ( Z_REFCOUNTED_P ( struc ) ) {
php_printf ( " \" refcount(%u) \n " , Z_REFCOUNT_P ( struc ) ) ;
} else {
PUTS ( " \" interned \n " ) ;
}
2002-02-10 06:52:35 +00:00
break ;
case IS_ARRAY :
2014-02-13 13:54:23 +00:00
myht = Z_ARRVAL_P ( struc ) ;
2020-07-11 06:37:25 +00:00
if ( ! ( GC_FLAGS ( myht ) & GC_IMMUTABLE ) ) {
2020-07-11 19:08:42 +00:00
if ( GC_IS_RECURSIVE ( myht ) ) {
PUTS ( " *RECURSION* \n " ) ;
return ;
2017-10-05 22:34:50 +00:00
}
2020-07-11 06:37:25 +00:00
GC_ADDREF ( myht ) ;
2020-07-11 19:08:42 +00:00
GC_PROTECT_RECURSION ( myht ) ;
2005-07-21 07:18:02 +00:00
}
2020-12-03 15:58:03 +00:00
count = zend_hash_num_elements ( myht ) ;
2021-01-12 09:26:17 +00:00
if ( Z_REFCOUNTED_P ( struc ) ) {
/* -1 because of ADDREF above. */
2021-03-03 15:28:39 +00:00
php_printf ( " array(%d) refcount(%u){ \n " , count , Z_REFCOUNT_P ( struc ) - 1 ) ;
2021-01-12 09:26:17 +00:00
} else {
2021-03-03 15:28:39 +00:00
php_printf ( " array(%d) interned { \n " , count ) ;
2021-01-12 09:26:17 +00:00
}
2020-12-03 15:58:03 +00:00
ZEND_HASH_FOREACH_KEY_VAL ( myht , index , key , val ) {
2014-12-13 22:06:14 +00:00
zval_array_element_dump ( val , index , key , level ) ;
2014-05-27 22:13:45 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2020-07-11 06:37:25 +00:00
if ( ! ( GC_FLAGS ( myht ) & GC_IMMUTABLE ) ) {
2020-07-11 19:08:42 +00:00
GC_UNPROTECT_RECURSION ( myht ) ;
2020-07-11 06:37:25 +00:00
GC_DELREF ( myht ) ;
2014-05-29 14:21:56 +00:00
}
2014-05-27 22:13:45 +00:00
if ( level > 1 ) {
php_printf ( " %*c " , level - 1 , ' ' ) ;
}
PUTS ( " } \n " ) ;
break ;
2002-02-10 06:52:35 +00:00
case IS_OBJECT :
2018-10-04 11:58:35 +00:00
myht = zend_get_properties_for ( struc , ZEND_PROP_PURPOSE_DEBUG ) ;
2014-05-27 22:13:45 +00:00
if ( myht ) {
2017-10-05 22:34:50 +00:00
if ( GC_IS_RECURSIVE ( myht ) ) {
2014-05-27 22:13:45 +00:00
PUTS ( " *RECURSION* \n " ) ;
2018-10-04 11:58:35 +00:00
zend_release_properties ( myht ) ;
2014-05-27 22:13:45 +00:00
return ;
}
2017-10-05 22:34:50 +00:00
GC_PROTECT_RECURSION ( myht ) ;
2005-07-21 07:18:02 +00:00
}
2014-12-13 22:06:14 +00:00
class_name = Z_OBJ_HANDLER_P ( struc , get_class_name ) ( Z_OBJ_P ( struc ) ) ;
2021-03-03 15:28:39 +00:00
php_printf ( " object(%s)#%d (%d) refcount(%u){ \n " , ZSTR_VAL ( class_name ) , Z_OBJ_HANDLE_P ( struc ) , myht ? zend_array_count ( myht ) : 0 , Z_REFCOUNT_P ( struc ) ) ;
2018-05-28 13:27:12 +00:00
zend_string_release_ex ( class_name , 0 ) ;
2003-02-01 03:52:31 +00:00
if ( myht ) {
2019-01-07 11:28:51 +00:00
ZEND_HASH_FOREACH_KEY_VAL ( myht , index , key , val ) {
zend_property_info * prop_info = NULL ;
if ( Z_TYPE_P ( val ) = = IS_INDIRECT ) {
val = Z_INDIRECT_P ( val ) ;
if ( key ) {
prop_info = zend_get_typed_property_info_for_slot ( Z_OBJ_P ( struc ) , val ) ;
}
}
if ( ! Z_ISUNDEF_P ( val ) | | prop_info ) {
zval_object_property_dump ( prop_info , val , index , key , level ) ;
}
2014-05-27 22:13:45 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2017-10-05 22:34:50 +00:00
GC_UNPROTECT_RECURSION ( myht ) ;
2018-10-04 11:58:35 +00:00
zend_release_properties ( myht ) ;
2003-02-01 03:52:31 +00:00
}
2002-02-10 06:52:35 +00:00
if ( level > 1 ) {
2007-11-02 19:40:39 +00:00
php_printf ( " %*c " , level - 1 , ' ' ) ;
2002-02-10 06:52:35 +00:00
}
PUTS ( " } \n " ) ;
break ;
case IS_RESOURCE : {
2014-12-13 22:06:14 +00:00
const char * type_name = zend_rsrc_list_get_rsrc_type ( Z_RES_P ( struc ) ) ;
2021-03-03 15:28:39 +00:00
php_printf ( " resource(%d) of type (%s) refcount(%u) \n " , Z_RES_P ( struc ) - > handle , type_name ? type_name : " Unknown " , Z_REFCOUNT_P ( struc ) ) ;
2002-02-10 06:52:35 +00:00
break ;
}
2014-03-26 14:07:31 +00:00
case IS_REFERENCE :
2021-03-03 15:28:39 +00:00
php_printf ( " reference refcount(%u) { \n " , Z_REFCOUNT_P ( struc ) ) ;
php_debug_zval_dump ( Z_REFVAL_P ( struc ) , level + 2 ) ;
if ( level > 1 ) {
php_printf ( " %*c " , level - 1 , ' ' ) ;
2014-03-26 14:07:31 +00:00
}
2021-03-03 15:28:39 +00:00
PUTS ( " } \n " ) ;
break ;
2002-02-10 06:52:35 +00:00
default :
2021-03-03 15:28:39 +00:00
PUTS ( " UNKNOWN:0 \n " ) ;
2002-02-10 06:52:35 +00:00
break ;
}
}
/* }}} */
2020-07-01 13:32:55 +00:00
/* {{{ Dumps a string representation of an internal zend value to output. */
2002-02-10 17:38:15 +00:00
PHP_FUNCTION ( debug_zval_dump )
2002-02-10 06:52:35 +00:00
{
2014-02-13 13:54:23 +00:00
zval * args ;
2002-02-10 06:52:35 +00:00
int argc ;
int i ;
2007-11-02 19:40:39 +00:00
2016-12-31 02:03:33 +00:00
ZEND_PARSE_PARAMETERS_START ( 1 , - 1 )
Z_PARAM_VARIADIC ( ' + ' , args , argc )
ZEND_PARSE_PARAMETERS_END ( ) ;
2007-11-02 19:40:39 +00:00
for ( i = 0 ; i < argc ; i + + ) {
2014-12-13 22:06:14 +00:00
php_debug_zval_dump ( & args [ i ] , 1 ) ;
2007-11-02 19:40:39 +00:00
}
2002-02-10 06:52:35 +00:00
}
/* }}} */
2010-07-09 21:11:37 +00:00
# define buffer_append_spaces(buf, num_spaces) \
do { \
char * tmp_spaces ; \
2014-10-22 07:25:53 +00:00
size_t tmp_spaces_len ; \
2010-07-09 21:11:37 +00:00
tmp_spaces_len = spprintf ( & tmp_spaces , 0 , " %*c " , num_spaces , ' ' ) ; \
smart_str_appendl ( buf , tmp_spaces , tmp_spaces_len ) ; \
efree ( tmp_spaces ) ; \
} while ( 0 ) ;
2014-12-13 22:06:14 +00:00
static void php_array_element_export ( zval * zv , zend_ulong index , zend_string * key , int level , smart_str * buf ) /* { { { */
2001-12-08 23:44:34 +00:00
{
2014-05-27 22:13:45 +00:00
if ( key = = NULL ) { /* numeric key */
2010-07-09 21:11:37 +00:00
buffer_append_spaces ( buf , level + 1 ) ;
2014-08-25 17:24:55 +00:00
smart_str_append_long ( buf , ( zend_long ) index ) ;
2010-07-09 21:11:37 +00:00
smart_str_appendl ( buf , " => " , 4 ) ;
2001-12-08 23:44:34 +00:00
} else { /* string key */
2014-02-23 11:25:26 +00:00
zend_string * tmp_str ;
2018-06-28 21:19:16 +00:00
zend_string * ckey = php_addcslashes ( key , " ' \\ " , 2 ) ;
2015-06-30 01:05:24 +00:00
tmp_str = php_str_to_str ( ZSTR_VAL ( ckey ) , ZSTR_LEN ( ckey ) , " \0 " , 1 , " ' . \" \\ 0 \" . ' " , 12 ) ;
2010-07-09 21:11:37 +00:00
buffer_append_spaces ( buf , level + 1 ) ;
smart_str_appendc ( buf , ' \' ' ) ;
2014-09-21 18:47:07 +00:00
smart_str_append ( buf , tmp_str ) ;
2010-07-09 21:11:37 +00:00
smart_str_appendl ( buf , " ' => " , 5 ) ;
2014-08-25 17:24:55 +00:00
zend_string_free ( ckey ) ;
zend_string_free ( tmp_str ) ;
2001-12-08 23:44:34 +00:00
}
2014-12-13 22:06:14 +00:00
php_var_export_ex ( zv , level + 2 , buf ) ;
2010-07-09 21:11:37 +00:00
smart_str_appendc ( buf , ' , ' ) ;
smart_str_appendc ( buf , ' \n ' ) ;
2001-12-08 23:44:34 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2001-12-08 23:44:34 +00:00
2014-12-13 22:06:14 +00:00
static void php_object_element_export ( zval * zv , zend_ulong index , zend_string * key , int level , smart_str * buf ) /* { { { */
2002-03-14 18:41:35 +00:00
{
2010-07-09 21:11:37 +00:00
buffer_append_spaces ( buf , level + 2 ) ;
2014-05-27 22:13:45 +00:00
if ( key ! = NULL ) {
2014-09-15 22:23:58 +00:00
const char * class_name , * prop_name ;
size_t prop_name_len ;
2014-02-22 12:51:26 +00:00
zend_string * pname_esc ;
2015-01-03 09:22:58 +00:00
2014-09-15 22:23:58 +00:00
zend_unmangle_property_name_ex ( key , & class_name , & prop_name , & prop_name_len ) ;
2018-06-28 21:19:16 +00:00
pname_esc = php_addcslashes_str ( prop_name , prop_name_len , " ' \\ " , 2 ) ;
2010-07-09 21:11:37 +00:00
smart_str_appendc ( buf , ' \' ' ) ;
2014-09-21 18:47:07 +00:00
smart_str_append ( buf , pname_esc ) ;
2010-07-09 21:11:37 +00:00
smart_str_appendc ( buf , ' \' ' ) ;
2018-05-28 13:27:12 +00:00
zend_string_release_ex ( pname_esc , 0 ) ;
2009-01-07 14:36:07 +00:00
} else {
2014-08-25 17:24:55 +00:00
smart_str_append_long ( buf , ( zend_long ) index ) ;
2002-03-14 18:41:35 +00:00
}
2010-07-09 21:11:37 +00:00
smart_str_appendl ( buf , " => " , 4 ) ;
2014-12-13 22:06:14 +00:00
php_var_export_ex ( zv , level + 2 , buf ) ;
2010-07-09 21:11:37 +00:00
smart_str_appendc ( buf , ' , ' ) ;
smart_str_appendc ( buf , ' \n ' ) ;
2002-03-14 18:41:35 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2002-03-14 18:41:35 +00:00
2014-12-13 22:06:14 +00:00
PHPAPI void php_var_export_ex ( zval * struc , int level , smart_str * buf ) /* { { { */
2001-12-08 23:44:34 +00:00
{
HashTable * myht ;
2016-06-26 13:03:01 +00:00
char tmp_str [ PHP_DOUBLE_MAX_LENGTH ] ;
2014-02-23 11:25:26 +00:00
zend_string * ztmp , * ztmp2 ;
2014-08-25 17:24:55 +00:00
zend_ulong index ;
2014-05-27 22:13:45 +00:00
zend_string * key ;
zval * val ;
2001-12-08 23:46:19 +00:00
2014-03-05 04:10:43 +00:00
again :
2014-02-13 13:54:23 +00:00
switch ( Z_TYPE_P ( struc ) ) {
2014-04-30 14:32:42 +00:00
case IS_FALSE :
smart_str_appendl ( buf , " false " , 5 ) ;
break ;
case IS_TRUE :
smart_str_appendl ( buf , " true " , 4 ) ;
2014-03-05 04:10:43 +00:00
break ;
case IS_NULL :
2012-08-05 15:36:36 +00:00
smart_str_appendl ( buf , " NULL " , 4 ) ;
2014-03-05 04:10:43 +00:00
break ;
2014-08-25 17:24:55 +00:00
case IS_LONG :
2019-03-11 14:35:02 +00:00
/* INT_MIN as a literal will be parsed as a float. Emit something like
* - 9223372036854775807 - 1 to avoid this . */
if ( Z_LVAL_P ( struc ) = = ZEND_LONG_MIN ) {
smart_str_append_long ( buf , ZEND_LONG_MIN + 1 ) ;
smart_str_appends ( buf , " -1 " ) ;
break ;
}
2014-08-25 17:24:55 +00:00
smart_str_append_long ( buf , Z_LVAL_P ( struc ) ) ;
2014-03-05 04:10:43 +00:00
break ;
case IS_DOUBLE :
2016-06-26 11:29:57 +00:00
php_gcvt ( Z_DVAL_P ( struc ) , ( int ) PG ( serialize_precision ) , ' . ' , ' E ' , tmp_str ) ;
smart_str_appends ( buf , tmp_str ) ;
/* Without a decimal point, PHP treats a number literal as an int.
2015-12-18 19:29:35 +00:00
* This check even works for scientific notation , because the
* mantissa always contains a decimal point .
2016-01-08 17:20:52 +00:00
* We need to check for finiteness , because INF , - INF and NAN
* must not have a decimal point added .
2016-06-26 11:29:57 +00:00
*/
2016-01-08 17:20:52 +00:00
if ( zend_finite ( Z_DVAL_P ( struc ) ) & & NULL = = strchr ( tmp_str , ' . ' ) ) {
2015-12-18 19:29:35 +00:00
smart_str_appendl ( buf , " .0 " , 2 ) ;
}
2014-03-05 04:10:43 +00:00
break ;
case IS_STRING :
2018-06-28 21:19:16 +00:00
ztmp = php_addcslashes ( Z_STR_P ( struc ) , " ' \\ " , 2 ) ;
2015-06-30 01:05:24 +00:00
ztmp2 = php_str_to_str ( ZSTR_VAL ( ztmp ) , ZSTR_LEN ( ztmp ) , " \0 " , 1 , " ' . \" \\ 0 \" . ' " , 12 ) ;
2014-03-05 04:10:43 +00:00
smart_str_appendc ( buf , ' \' ' ) ;
2014-09-21 18:47:07 +00:00
smart_str_append ( buf , ztmp2 ) ;
2014-03-05 04:10:43 +00:00
smart_str_appendc ( buf , ' \' ' ) ;
2014-08-25 17:24:55 +00:00
zend_string_free ( ztmp ) ;
zend_string_free ( ztmp2 ) ;
2014-03-05 04:10:43 +00:00
break ;
case IS_ARRAY :
myht = Z_ARRVAL_P ( struc ) ;
2017-10-05 22:34:50 +00:00
if ( ! ( GC_FLAGS ( myht ) & GC_IMMUTABLE ) ) {
if ( GC_IS_RECURSIVE ( myht ) ) {
smart_str_appendl ( buf , " NULL " , 4 ) ;
zend_error ( E_WARNING , " var_export does not handle circular references " ) ;
return ;
}
2020-07-11 06:37:25 +00:00
GC_ADDREF ( myht ) ;
2017-10-05 22:34:50 +00:00
GC_PROTECT_RECURSION ( myht ) ;
2014-03-05 04:10:43 +00:00
}
if ( level > 1 ) {
smart_str_appendc ( buf , ' \n ' ) ;
buffer_append_spaces ( buf , level - 1 ) ;
}
smart_str_appendl ( buf , " array ( \n " , 8 ) ;
2020-12-03 15:58:03 +00:00
ZEND_HASH_FOREACH_KEY_VAL ( myht , index , key , val ) {
2014-12-13 22:06:14 +00:00
php_array_element_export ( val , index , key , level , buf ) ;
2014-05-27 22:13:45 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2017-10-05 22:34:50 +00:00
if ( ! ( GC_FLAGS ( myht ) & GC_IMMUTABLE ) ) {
GC_UNPROTECT_RECURSION ( myht ) ;
2020-07-10 22:14:22 +00:00
GC_DELREF ( myht ) ;
2014-05-29 14:21:56 +00:00
}
2014-03-05 04:10:43 +00:00
if ( level > 1 ) {
buffer_append_spaces ( buf , level - 1 ) ;
}
smart_str_appendc ( buf , ' ) ' ) ;
2015-01-03 09:22:58 +00:00
2014-03-05 04:10:43 +00:00
break ;
case IS_OBJECT :
2018-10-04 11:58:35 +00:00
myht = zend_get_properties_for ( struc , ZEND_PROP_PURPOSE_VAR_EXPORT ) ;
2014-05-27 22:13:45 +00:00
if ( myht ) {
2017-10-05 22:34:50 +00:00
if ( GC_IS_RECURSIVE ( myht ) ) {
2014-05-27 22:13:45 +00:00
smart_str_appendl ( buf , " NULL " , 4 ) ;
zend_error ( E_WARNING , " var_export does not handle circular references " ) ;
2018-10-04 11:58:35 +00:00
zend_release_properties ( myht ) ;
2014-05-27 22:13:45 +00:00
return ;
} else {
2019-11-25 14:44:15 +00:00
GC_TRY_PROTECT_RECURSION ( myht ) ;
2014-05-27 22:13:45 +00:00
}
2014-03-05 04:10:43 +00:00
}
if ( level > 1 ) {
smart_str_appendc ( buf , ' \n ' ) ;
buffer_append_spaces ( buf , level - 1 ) ;
}
2010-07-09 21:11:37 +00:00
2020-06-10 21:10:18 +00:00
zend_class_entry * ce = Z_OBJCE_P ( struc ) ;
bool is_enum = ce - > ce_flags & ZEND_ACC_ENUM ;
2018-07-05 20:02:59 +00:00
/* stdClass has no __set_state method, but can be casted to */
2020-06-10 21:10:18 +00:00
if ( ce = = zend_standard_class_def ) {
2018-07-05 20:02:59 +00:00
smart_str_appendl ( buf , " (object) array( \n " , 16 ) ;
} else {
2020-06-10 21:10:18 +00:00
smart_str_append ( buf , ce - > name ) ;
if ( is_enum ) {
zend_object * zobj = Z_OBJ_P ( struc ) ;
zval * case_name_zval = zend_enum_fetch_case_name ( zobj ) ;
smart_str_appendl ( buf , " :: " , 2 ) ;
smart_str_append ( buf , Z_STR_P ( case_name_zval ) ) ;
} else {
smart_str_appendl ( buf , " ::__set_state(array( \n " , 21 ) ;
}
2018-07-05 20:02:59 +00:00
}
2010-07-09 21:11:37 +00:00
2020-06-10 21:10:18 +00:00
if ( myht & & ! is_enum ) {
2014-05-27 22:13:45 +00:00
ZEND_HASH_FOREACH_KEY_VAL_IND ( myht , index , key , val ) {
2014-12-13 22:06:14 +00:00
php_object_element_export ( val , index , key , level , buf ) ;
2014-05-27 22:13:45 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2019-11-25 14:44:15 +00:00
GC_TRY_UNPROTECT_RECURSION ( myht ) ;
2020-06-10 21:10:18 +00:00
}
if ( myht ) {
2018-10-04 11:58:35 +00:00
zend_release_properties ( myht ) ;
2014-03-05 04:10:43 +00:00
}
2020-06-10 21:10:18 +00:00
if ( level > 1 & & ! is_enum ) {
2014-03-05 04:10:43 +00:00
buffer_append_spaces ( buf , level - 1 ) ;
}
2020-06-10 21:10:18 +00:00
if ( ce = = zend_standard_class_def ) {
2018-07-05 20:02:59 +00:00
smart_str_appendc ( buf , ' ) ' ) ;
2020-06-10 21:10:18 +00:00
} else if ( ! is_enum ) {
2018-07-05 20:02:59 +00:00
smart_str_appendl ( buf , " )) " , 2 ) ;
}
2014-03-05 04:10:43 +00:00
break ;
case IS_REFERENCE :
struc = Z_REFVAL_P ( struc ) ;
goto again ;
break ;
default :
smart_str_appendl ( buf , " NULL " , 4 ) ;
break ;
2001-12-08 23:44:34 +00:00
}
}
/* }}} */
2010-07-09 21:11:37 +00:00
/* FOR BC reasons, this will always perform and then print */
2014-12-13 22:06:14 +00:00
PHPAPI void php_var_export ( zval * struc , int level ) /* { { { */
2010-07-09 21:11:37 +00:00
{
smart_str buf = { 0 } ;
2014-12-13 22:06:14 +00:00
php_var_export_ex ( struc , level , & buf ) ;
2014-02-18 09:42:46 +00:00
smart_str_0 ( & buf ) ;
2015-06-30 01:05:24 +00:00
PHPWRITE ( ZSTR_VAL ( buf . s ) , ZSTR_LEN ( buf . s ) ) ;
2010-07-09 21:11:37 +00:00
smart_str_free ( & buf ) ;
}
/* }}} */
2020-07-01 13:32:55 +00:00
/* {{{ Outputs or returns a string representation of a variable */
2001-12-08 23:44:34 +00:00
PHP_FUNCTION ( var_export )
{
2001-12-15 14:45:59 +00:00
zval * var ;
2021-01-15 11:30:54 +00:00
bool return_output = 0 ;
2010-07-09 21:11:37 +00:00
smart_str buf = { 0 } ;
2007-11-02 19:40:39 +00:00
2016-12-31 02:03:33 +00:00
ZEND_PARSE_PARAMETERS_START ( 1 , 2 )
2017-06-19 09:55:59 +00:00
Z_PARAM_ZVAL ( var )
2016-12-31 02:03:33 +00:00
Z_PARAM_OPTIONAL
Z_PARAM_BOOL ( return_output )
ZEND_PARSE_PARAMETERS_END ( ) ;
2007-11-02 19:40:39 +00:00
2014-12-13 22:06:14 +00:00
php_var_export_ex ( var , 1 , & buf ) ;
2010-07-09 21:11:37 +00:00
smart_str_0 ( & buf ) ;
2001-12-15 14:45:59 +00:00
2002-10-03 13:32:01 +00:00
if ( return_output ) {
2015-03-12 13:53:51 +00:00
RETURN_NEW_STR ( buf . s ) ;
2010-07-09 21:11:37 +00:00
} else {
2015-06-30 01:05:24 +00:00
PHPWRITE ( ZSTR_VAL ( buf . s ) , ZSTR_LEN ( buf . s ) ) ;
2014-02-18 09:42:46 +00:00
smart_str_free ( & buf ) ;
2001-12-15 14:45:59 +00:00
}
2001-12-08 23:44:34 +00:00
}
/* }}} */
2014-12-13 22:06:14 +00:00
static void php_var_serialize_intern ( smart_str * buf , zval * struc , php_serialize_data_t var_hash ) ;
2001-08-04 03:30:38 +00:00
2014-12-13 22:06:14 +00:00
static inline zend_long php_add_var_hash ( php_serialize_data_t data , zval * var ) /* { { { */
2001-07-15 14:08:58 +00:00
{
2014-09-21 21:42:55 +00:00
zval * zv ;
zend_ulong key ;
2021-01-15 11:30:54 +00:00
bool is_ref = Z_ISREF_P ( var ) ;
2000-10-30 17:10:06 +00:00
2014-09-21 21:42:55 +00:00
data - > n + = 1 ;
2021-02-26 10:30:19 +00:00
if ( ! is_ref & & ( Z_TYPE_P ( var ) ! = IS_OBJECT | | Z_REFCOUNT_P ( var ) = = 1 ) ) {
2014-09-21 21:42:55 +00:00
return 0 ;
2004-07-03 16:10:28 +00:00
}
2014-09-21 21:42:55 +00:00
/* References to objects are treated as if the reference didn't exist */
2014-09-24 09:58:13 +00:00
if ( is_ref & & Z_TYPE_P ( Z_REFVAL_P ( var ) ) = = IS_OBJECT ) {
2014-09-21 21:42:55 +00:00
var = Z_REFVAL_P ( var ) ;
2000-10-30 17:10:06 +00:00
}
2007-11-02 19:40:39 +00:00
2014-09-21 21:42:55 +00:00
/* Index for the variable is stored using the numeric value of the pointer to
* the zend_refcounted struct */
key = ( zend_ulong ) ( zend_uintptr_t ) Z_COUNTED_P ( var ) ;
zv = zend_hash_index_find ( & data - > ht , key ) ;
if ( zv ) {
2014-09-24 09:58:13 +00:00
/* References are only counted once, undo the data->n increment above */
2020-11-25 16:23:42 +00:00
if ( is_ref & & Z_LVAL_P ( zv ) ! = - 1 ) {
2014-09-24 09:58:13 +00:00
data - > n - = 1 ;
}
2014-09-21 21:42:55 +00:00
return Z_LVAL_P ( zv ) ;
} else {
zval zv_n ;
ZVAL_LONG ( & zv_n , data - > n ) ;
zend_hash_index_add_new ( & data - > ht , key , & zv_n ) ;
/* Additionally to the index, we also store the variable, to ensure that it is
* not destroyed during serialization and its pointer reused . The variable is
* stored at the numeric value of the pointer + 1 , which cannot be the location
* of another zend_refcounted structure . */
zend_hash_index_add_new ( & data - > ht , key + 1 , var ) ;
Z_ADDREF_P ( var ) ;
return 0 ;
}
2000-10-30 17:10:06 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2000-10-30 17:10:06 +00:00
2014-08-25 17:24:55 +00:00
static inline void php_var_serialize_long ( smart_str * buf , zend_long val ) /* { { { */
2001-08-04 03:30:38 +00:00
{
2021-02-26 10:30:19 +00:00
char b [ 32 ] ;
char * s = zend_print_long_to_buf ( b + sizeof ( b ) - 1 , val ) ;
size_t l = b + sizeof ( b ) - 1 - s ;
2021-05-07 14:42:17 +00:00
char * res = smart_str_extend ( buf , 2 + l + 1 ) ;
2021-02-26 10:30:19 +00:00
memcpy ( res , " i: " , 2 ) ;
res + = 2 ;
memcpy ( res , s , l ) ;
res [ l ] = ' ; ' ;
2001-08-04 03:30:38 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2001-08-04 03:30:38 +00:00
2014-09-19 20:59:58 +00:00
static inline void php_var_serialize_string ( smart_str * buf , char * str , size_t len ) /* { { { */
2001-08-04 03:30:38 +00:00
{
2021-02-26 10:30:19 +00:00
char b [ 32 ] ;
char * s = zend_print_long_to_buf ( b + sizeof ( b ) - 1 , len ) ;
size_t l = b + sizeof ( b ) - 1 - s ;
2021-05-07 14:42:17 +00:00
char * res = smart_str_extend ( buf , 2 + l + 2 + len + 2 ) ;
2021-02-26 10:30:19 +00:00
memcpy ( res , " s: " , 2 ) ;
res + = 2 ;
memcpy ( res , s , l ) ;
res + = l ;
memcpy ( res , " : \" " , 2 ) ;
res + = 2 ;
memcpy ( res , str , len ) ;
res + = len ;
memcpy ( res , " \" ; " , 2 ) ;
2001-08-04 03:30:38 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2001-08-04 03:30:38 +00:00
2021-01-15 11:30:54 +00:00
static inline bool php_var_serialize_class_name ( smart_str * buf , zval * struc ) /* { { { */
2001-08-04 03:30:38 +00:00
{
2021-05-07 14:42:17 +00:00
char b [ 32 ] ;
2001-08-04 03:30:38 +00:00
PHP_CLASS_ATTRIBUTES ;
2006-12-08 20:59:31 +00:00
PHP_SET_CLASS_ATTRIBUTES ( struc ) ;
2021-02-26 14:48:36 +00:00
size_t class_name_len = ZSTR_LEN ( class_name ) ;
2021-05-07 14:42:17 +00:00
char * s = zend_print_long_to_buf ( b + sizeof ( b ) - 1 , class_name_len ) ;
size_t l = b + sizeof ( b ) - 1 - s ;
char * res = smart_str_extend ( buf , 2 + l + 2 + class_name_len + 2 ) ;
2021-02-26 10:30:19 +00:00
memcpy ( res , " O: " , 2 ) ;
res + = 2 ;
memcpy ( res , s , l ) ;
res + = l ;
memcpy ( res , " : \" " , 2 ) ;
res + = 2 ;
2021-02-26 14:48:36 +00:00
memcpy ( res , ZSTR_VAL ( class_name ) , class_name_len ) ;
res + = class_name_len ;
2021-02-26 10:30:19 +00:00
memcpy ( res , " \" : " , 2 ) ;
2001-08-04 03:30:38 +00:00
PHP_CLEANUP_CLASS_ATTRIBUTES ( ) ;
2004-03-18 16:54:36 +00:00
return incomplete_class ;
2001-08-04 03:30:38 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2001-08-04 03:30:38 +00:00
2021-02-25 09:16:22 +00:00
static zend_result php_var_serialize_call_sleep ( zend_object * obj , zend_function * fn , zval * retval ) /* { { { */
2017-03-12 20:32:47 +00:00
{
2021-02-25 09:16:22 +00:00
zend_result res ;
zend_fcall_info fci ;
zend_fcall_info_cache fci_cache ;
fci . size = sizeof ( fci ) ;
fci . object = obj ;
fci . retval = retval ;
fci . param_count = 0 ;
fci . params = NULL ;
fci . named_params = NULL ;
ZVAL_UNDEF ( & fci . function_name ) ;
fci_cache . function_handler = fn ;
fci_cache . object = obj ;
fci_cache . called_scope = obj - > ce ;
2017-03-12 20:32:47 +00:00
BG ( serialize_lock ) + + ;
2021-02-25 09:16:22 +00:00
res = zend_call_function ( & fci , & fci_cache ) ;
2017-03-12 20:32:47 +00:00
BG ( serialize_lock ) - - ;
if ( res = = FAILURE | | Z_ISUNDEF_P ( retval ) ) {
zval_ptr_dtor ( retval ) ;
return FAILURE ;
}
if ( ! HASH_OF ( retval ) ) {
zval_ptr_dtor ( retval ) ;
2021-02-25 09:16:22 +00:00
php_error_docref ( NULL , E_WARNING , " %s::__sleep() should return an array only containing the names of instance-variables to serialize " , ZSTR_VAL ( obj - > ce - > name ) ) ;
2017-03-12 20:32:47 +00:00
return FAILURE ;
}
return SUCCESS ;
}
/* }}} */
2019-01-22 16:47:16 +00:00
static int php_var_serialize_call_magic_serialize ( zval * retval , zval * obj ) /* { { { */
{
BG ( serialize_lock ) + + ;
2020-06-26 08:54:40 +00:00
zend_call_known_instance_method_with_0_params (
Z_OBJCE_P ( obj ) - > __serialize , Z_OBJ_P ( obj ) , retval ) ;
2019-01-22 16:47:16 +00:00
BG ( serialize_lock ) - - ;
2020-06-26 08:54:40 +00:00
if ( EG ( exception ) ) {
2019-01-22 16:47:16 +00:00
zval_ptr_dtor ( retval ) ;
return FAILURE ;
}
if ( Z_TYPE_P ( retval ) ! = IS_ARRAY ) {
zval_ptr_dtor ( retval ) ;
2019-04-09 15:27:02 +00:00
zend_type_error ( " %s::__serialize() must return an array " , ZSTR_VAL ( Z_OBJCE_P ( obj ) - > name ) ) ;
2019-01-22 16:47:16 +00:00
return FAILURE ;
}
return SUCCESS ;
}
/* }}} */
2020-01-02 10:11:01 +00:00
static int php_var_serialize_try_add_sleep_prop (
2020-01-03 14:35:10 +00:00
HashTable * ht , HashTable * props , zend_string * name , zend_string * error_name , zval * struc ) /* {{{ */
2017-03-12 20:32:47 +00:00
{
2020-01-02 10:11:01 +00:00
zval * val = zend_hash_find ( props , name ) ;
if ( val = = NULL ) {
return FAILURE ;
}
2016-04-09 17:01:04 +00:00
2020-01-02 10:11:01 +00:00
if ( Z_TYPE_P ( val ) = = IS_INDIRECT ) {
val = Z_INDIRECT_P ( val ) ;
if ( Z_TYPE_P ( val ) = = IS_UNDEF ) {
2020-01-03 14:35:10 +00:00
zend_property_info * info = zend_get_typed_property_info_for_slot ( Z_OBJ_P ( struc ) , val ) ;
if ( info ) {
2020-04-15 22:11:38 +00:00
return SUCCESS ;
2020-01-03 14:35:10 +00:00
}
2020-01-02 10:11:01 +00:00
return FAILURE ;
2016-04-09 17:01:04 +00:00
}
2020-01-02 10:11:01 +00:00
}
2017-03-12 20:32:47 +00:00
2020-01-02 10:11:01 +00:00
if ( ! zend_hash_add ( ht , name , val ) ) {
php_error_docref ( NULL , E_NOTICE ,
2020-09-10 11:28:18 +00:00
" \" %s \" is returned from __sleep() multiple times " , ZSTR_VAL ( error_name ) ) ;
2020-01-02 10:11:01 +00:00
return SUCCESS ;
}
Z_TRY_ADDREF_P ( val ) ;
return SUCCESS ;
2016-04-09 17:01:04 +00:00
}
/* }}} */
2020-01-03 14:35:10 +00:00
static int php_var_serialize_get_sleep_props (
2020-01-02 10:11:01 +00:00
HashTable * ht , zval * struc , HashTable * sleep_retval ) /* {{{ */
2001-08-04 03:30:38 +00:00
{
2017-03-12 20:32:47 +00:00
zend_class_entry * ce = Z_OBJCE_P ( struc ) ;
2020-01-02 10:11:01 +00:00
HashTable * props = zend_get_properties_for ( struc , ZEND_PROP_PURPOSE_SERIALIZE ) ;
zval * name_val ;
2020-01-03 14:35:10 +00:00
int retval = SUCCESS ;
2017-03-12 20:32:47 +00:00
2020-01-02 10:11:01 +00:00
zend_hash_init ( ht , zend_hash_num_elements ( sleep_retval ) , NULL , ZVAL_PTR_DTOR , 0 ) ;
2020-01-03 14:35:10 +00:00
/* TODO: Rewrite this by fetching the property info instead of trying out different
* name manglings ? */
2020-01-02 10:11:01 +00:00
ZEND_HASH_FOREACH_VAL ( sleep_retval , name_val ) {
zend_string * name , * tmp_name , * priv_name , * prot_name ;
2017-03-12 21:15:46 +00:00
2020-01-02 10:11:01 +00:00
ZVAL_DEREF ( name_val ) ;
if ( Z_TYPE_P ( name_val ) ! = IS_STRING ) {
2020-09-10 11:28:18 +00:00
php_error_docref ( NULL , E_WARNING ,
" %s::__sleep() should return an array only containing the names of instance-variables to serialize " ,
2020-04-28 06:17:21 +00:00
ZSTR_VAL ( ce - > name ) ) ;
2020-01-02 10:11:01 +00:00
}
2017-03-12 21:15:46 +00:00
2020-01-02 10:11:01 +00:00
name = zval_get_tmp_string ( name_val , & tmp_name ) ;
2020-01-03 14:35:10 +00:00
if ( php_var_serialize_try_add_sleep_prop ( ht , props , name , name , struc ) = = SUCCESS ) {
2020-01-02 10:11:01 +00:00
zend_tmp_string_release ( tmp_name ) ;
2017-03-12 21:15:46 +00:00
continue ;
}
2020-01-03 14:35:10 +00:00
if ( EG ( exception ) ) {
zend_tmp_string_release ( tmp_name ) ;
retval = FAILURE ;
break ;
}
2017-03-12 21:15:46 +00:00
priv_name = zend_mangle_property_name (
2020-01-02 10:11:01 +00:00
ZSTR_VAL ( ce - > name ) , ZSTR_LEN ( ce - > name ) ,
ZSTR_VAL ( name ) , ZSTR_LEN ( name ) , ce - > type & ZEND_INTERNAL_CLASS ) ;
2020-01-03 14:35:10 +00:00
if ( php_var_serialize_try_add_sleep_prop ( ht , props , priv_name , name , struc ) = = SUCCESS ) {
2020-01-02 10:11:01 +00:00
zend_tmp_string_release ( tmp_name ) ;
zend_string_release ( priv_name ) ;
2017-03-12 21:15:46 +00:00
continue ;
}
2020-01-02 10:11:01 +00:00
zend_string_release ( priv_name ) ;
2017-03-12 21:15:46 +00:00
2020-01-03 14:35:10 +00:00
if ( EG ( exception ) ) {
zend_tmp_string_release ( tmp_name ) ;
retval = FAILURE ;
break ;
}
2017-03-12 21:15:46 +00:00
prot_name = zend_mangle_property_name (
2020-01-02 10:11:01 +00:00
" * " , 1 , ZSTR_VAL ( name ) , ZSTR_LEN ( name ) , ce - > type & ZEND_INTERNAL_CLASS ) ;
2020-01-03 14:35:10 +00:00
if ( php_var_serialize_try_add_sleep_prop ( ht , props , prot_name , name , struc ) = = SUCCESS ) {
2020-01-02 10:11:01 +00:00
zend_tmp_string_release ( tmp_name ) ;
zend_string_release ( prot_name ) ;
2017-03-12 21:15:46 +00:00
continue ;
2017-03-12 20:32:47 +00:00
}
2020-01-02 10:11:01 +00:00
zend_string_release ( prot_name ) ;
2017-03-12 21:15:46 +00:00
2020-01-03 14:35:10 +00:00
if ( EG ( exception ) ) {
zend_tmp_string_release ( tmp_name ) ;
retval = FAILURE ;
break ;
}
2020-09-10 11:28:18 +00:00
php_error_docref ( NULL , E_WARNING ,
2020-01-02 10:11:01 +00:00
" \" %s \" returned as member variable from __sleep() but does not exist " , ZSTR_VAL ( name ) ) ;
zend_tmp_string_release ( tmp_name ) ;
2017-03-12 20:32:47 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2020-01-03 14:35:10 +00:00
2020-01-02 10:11:01 +00:00
zend_release_properties ( props ) ;
2020-01-03 14:35:10 +00:00
return retval ;
2001-08-04 03:30:38 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2001-08-04 03:30:38 +00:00
2021-01-15 11:30:54 +00:00
static void php_var_serialize_nested_data ( smart_str * buf , zval * struc , HashTable * ht , uint32_t count , bool incomplete_class , php_serialize_data_t var_hash ) /* { { { */
2020-01-02 09:43:01 +00:00
{
smart_str_append_unsigned ( buf , count ) ;
smart_str_appendl ( buf , " :{ " , 2 ) ;
if ( count > 0 ) {
zend_string * key ;
zval * data ;
zend_ulong index ;
ZEND_HASH_FOREACH_KEY_VAL_IND ( ht , index , key , data ) {
2020-12-31 00:05:12 +00:00
if ( incomplete_class & & zend_string_equals_literal ( key , MAGIC_MEMBER ) ) {
2021-03-01 11:53:30 +00:00
incomplete_class = 0 ;
2020-01-02 09:43:01 +00:00
continue ;
}
if ( ! key ) {
php_var_serialize_long ( buf , index ) ;
} else {
php_var_serialize_string ( buf , ZSTR_VAL ( key ) , ZSTR_LEN ( key ) ) ;
}
if ( Z_ISREF_P ( data ) & & Z_REFCOUNT_P ( data ) = = 1 ) {
data = Z_REFVAL_P ( data ) ;
}
/* we should still add element even if it's not OK,
* since we already wrote the length of the array before */
if ( Z_TYPE_P ( data ) = = IS_ARRAY ) {
if ( UNEXPECTED ( Z_IS_RECURSIVE_P ( data ) )
| | UNEXPECTED ( Z_TYPE_P ( struc ) = = IS_ARRAY & & Z_ARR_P ( data ) = = Z_ARR_P ( struc ) ) ) {
php_add_var_hash ( var_hash , struc ) ;
smart_str_appendl ( buf , " N; " , 2 ) ;
} else {
if ( Z_REFCOUNTED_P ( data ) ) {
Z_PROTECT_RECURSION_P ( data ) ;
}
php_var_serialize_intern ( buf , data , var_hash ) ;
if ( Z_REFCOUNTED_P ( data ) ) {
Z_UNPROTECT_RECURSION_P ( data ) ;
}
}
} else {
php_var_serialize_intern ( buf , data , var_hash ) ;
}
} ZEND_HASH_FOREACH_END ( ) ;
}
2017-03-12 20:32:47 +00:00
smart_str_appendc ( buf , ' } ' ) ;
2020-01-02 09:43:01 +00:00
}
/* }}} */
2016-04-09 17:01:04 +00:00
2020-01-02 10:11:01 +00:00
static void php_var_serialize_class ( smart_str * buf , zval * struc , zval * retval_ptr , php_serialize_data_t var_hash ) /* { { { */
{
HashTable props ;
2020-01-03 14:35:10 +00:00
if ( php_var_serialize_get_sleep_props ( & props , struc , HASH_OF ( retval_ptr ) ) = = SUCCESS ) {
php_var_serialize_class_name ( buf , struc ) ;
php_var_serialize_nested_data (
buf , struc , & props , zend_hash_num_elements ( & props ) , /* incomplete_class */ 0 , var_hash ) ;
}
2020-01-02 10:11:01 +00:00
zend_hash_destroy ( & props ) ;
2001-08-04 03:30:38 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
2001-08-04 03:30:38 +00:00
2014-12-13 22:06:14 +00:00
static void php_var_serialize_intern ( smart_str * buf , zval * struc , php_serialize_data_t var_hash ) /* { { { */
1999-04-17 00:37:12 +00:00
{
2014-10-22 07:37:25 +00:00
zend_long var_already ;
1999-09-15 11:08:25 +00:00
HashTable * myht ;
1999-04-17 00:37:12 +00:00
2013-03-09 15:00:58 +00:00
if ( EG ( exception ) ) {
return ;
}
2014-12-13 22:06:14 +00:00
if ( var_hash & & ( var_already = php_add_var_hash ( var_hash , struc ) ) ) {
2019-02-21 11:04:49 +00:00
if ( var_already = = - 1 ) {
/* Reference to an object that failed to serialize, replace with null. */
smart_str_appendl ( buf , " N; " , 2 ) ;
return ;
} else if ( Z_ISREF_P ( struc ) ) {
2004-02-03 14:12:59 +00:00
smart_str_appendl ( buf , " R: " , 2 ) ;
2014-09-21 21:42:55 +00:00
smart_str_append_long ( buf , var_already ) ;
2004-02-03 14:12:59 +00:00
smart_str_appendc ( buf , ' ; ' ) ;
2004-02-05 09:07:46 +00:00
return ;
2007-11-02 19:40:39 +00:00
} else if ( Z_TYPE_P ( struc ) = = IS_OBJECT ) {
2004-02-03 14:12:59 +00:00
smart_str_appendl ( buf , " r: " , 2 ) ;
2014-09-21 21:42:55 +00:00
smart_str_append_long ( buf , var_already ) ;
2004-02-03 14:12:59 +00:00
smart_str_appendc ( buf , ' ; ' ) ;
2004-02-05 09:07:46 +00:00
return ;
2004-02-03 14:12:59 +00:00
}
2000-10-30 17:10:06 +00:00
}
2014-02-26 03:08:13 +00:00
again :
2006-12-08 20:59:31 +00:00
switch ( Z_TYPE_P ( struc ) ) {
2014-04-30 14:32:42 +00:00
case IS_FALSE :
smart_str_appendl ( buf , " b:0; " , 4 ) ;
return ;
case IS_TRUE :
smart_str_appendl ( buf , " b:1; " , 4 ) ;
1999-07-01 09:26:05 +00:00
return ;
2000-01-04 13:22:58 +00:00
case IS_NULL :
2001-08-03 07:25:27 +00:00
smart_str_appendl ( buf , " N; " , 2 ) ;
2000-01-02 11:49:27 +00:00
return ;
2014-08-25 17:24:55 +00:00
case IS_LONG :
php_var_serialize_long ( buf , Z_LVAL_P ( struc ) ) ;
1999-04-17 00:37:12 +00:00
return ;
2001-08-04 03:30:38 +00:00
case IS_DOUBLE : {
2021-05-07 14:42:17 +00:00
char tmp_str [ PHP_DOUBLE_MAX_LENGTH ] ;
2015-08-30 08:13:24 +00:00
php_gcvt ( Z_DVAL_P ( struc ) , ( int ) PG ( serialize_precision ) , ' . ' , ' E ' , tmp_str ) ;
2021-02-26 10:30:19 +00:00
2021-05-07 14:42:17 +00:00
size_t len = strlen ( tmp_str ) ;
char * res = smart_str_extend ( buf , 2 + len + 1 ) ;
2021-02-26 10:30:19 +00:00
memcpy ( res , " d: " , 2 ) ;
res + = 2 ;
memcpy ( res , tmp_str , len ) ;
res [ len ] = ' ; ' ;
2015-08-04 23:12:10 +00:00
return ;
}
1999-04-17 00:37:12 +00:00
2001-08-03 07:25:27 +00:00
case IS_STRING :
2014-08-25 17:24:55 +00:00
php_var_serialize_string ( buf , Z_STRVAL_P ( struc ) , Z_STRLEN_P ( struc ) ) ;
1999-04-17 00:37:12 +00:00
return ;
2001-08-04 03:30:38 +00:00
2000-03-16 02:15:41 +00:00
case IS_OBJECT : {
2014-10-09 11:58:14 +00:00
zend_class_entry * ce = Z_OBJCE_P ( struc ) ;
2021-01-15 11:30:54 +00:00
bool incomplete_class ;
2020-01-02 09:43:01 +00:00
uint32_t count ;
2005-06-28 09:46:30 +00:00
2020-06-10 21:10:18 +00:00
if ( ce - > ce_flags & ZEND_ACC_ENUM ) {
PHP_CLASS_ATTRIBUTES ;
zval * case_name_zval = zend_enum_fetch_case_name ( Z_OBJ_P ( struc ) ) ;
PHP_SET_CLASS_ATTRIBUTES ( struc ) ;
smart_str_appendl ( buf , " E: " , 2 ) ;
smart_str_append_unsigned ( buf , ZSTR_LEN ( class_name ) + strlen ( " : " ) + Z_STRLEN_P ( case_name_zval ) ) ;
smart_str_appendl ( buf , " : \" " , 2 ) ;
smart_str_append ( buf , class_name ) ;
smart_str_appendc ( buf , ' : ' ) ;
smart_str_append ( buf , Z_STR_P ( case_name_zval ) ) ;
smart_str_appendl ( buf , " \" ; " , 2 ) ;
PHP_CLEANUP_CLASS_ATTRIBUTES ( ) ;
return ;
}
2020-06-26 08:54:40 +00:00
if ( ce - > __serialize ) {
2019-01-22 16:47:16 +00:00
zval retval , obj ;
zend_string * key ;
zval * data ;
zend_ulong index ;
2020-06-17 10:34:04 +00:00
ZVAL_OBJ_COPY ( & obj , Z_OBJ_P ( struc ) ) ;
2019-01-22 16:47:16 +00:00
if ( php_var_serialize_call_magic_serialize ( & retval , & obj ) = = FAILURE ) {
if ( ! EG ( exception ) ) {
smart_str_appendl ( buf , " N; " , 2 ) ;
}
zval_ptr_dtor ( & obj ) ;
return ;
}
php_var_serialize_class_name ( buf , & obj ) ;
2021-02-26 10:30:19 +00:00
smart_str_append_unsigned ( buf , zend_hash_num_elements ( Z_ARRVAL ( retval ) ) ) ;
2019-01-22 16:47:16 +00:00
smart_str_appendl ( buf , " :{ " , 2 ) ;
2021-02-26 10:30:19 +00:00
ZEND_HASH_FOREACH_KEY_VAL ( Z_ARRVAL ( retval ) , index , key , data ) {
2019-01-22 16:47:16 +00:00
if ( ! key ) {
php_var_serialize_long ( buf , index ) ;
} else {
php_var_serialize_string ( buf , ZSTR_VAL ( key ) , ZSTR_LEN ( key ) ) ;
}
if ( Z_ISREF_P ( data ) & & Z_REFCOUNT_P ( data ) = = 1 ) {
data = Z_REFVAL_P ( data ) ;
}
php_var_serialize_intern ( buf , data , var_hash ) ;
} ZEND_HASH_FOREACH_END ( ) ;
smart_str_appendc ( buf , ' } ' ) ;
zval_ptr_dtor ( & obj ) ;
zval_ptr_dtor ( & retval ) ;
return ;
}
2014-10-09 11:58:14 +00:00
if ( ce - > serialize ! = NULL ) {
2005-02-23 11:17:52 +00:00
/* has custom handler */
unsigned char * serialized_data = NULL ;
2014-09-15 14:32:18 +00:00
size_t serialized_length ;
2005-02-23 11:17:52 +00:00
2014-12-13 22:06:14 +00:00
if ( ce - > serialize ( struc , & serialized_data , & serialized_length , ( zend_serialize_data * ) var_hash ) = = SUCCESS ) {
2021-05-07 14:42:17 +00:00
char b1 [ 32 ] , b2 [ 32 ] ;
char * s1 = zend_print_long_to_buf ( b1 + sizeof ( b1 ) - 1 , ZSTR_LEN ( Z_OBJCE_P ( struc ) - > name ) ) ;
size_t l1 = b1 + sizeof ( b1 ) - 1 - s1 ;
char * s2 = zend_print_long_to_buf ( b2 + sizeof ( b2 ) - 1 , serialized_length ) ;
size_t l2 = b2 + sizeof ( b2 ) - 1 - s2 ;
char * res = smart_str_extend ( buf , 2 + l1 + 2 + ZSTR_LEN ( Z_OBJCE_P ( struc ) - > name ) + 2 + l2 + 2 + serialized_length + 1 ) ;
2021-02-26 10:30:19 +00:00
memcpy ( res , " C: " , 2 ) ;
res + = 2 ;
memcpy ( res , s1 , l1 ) ;
res + = l1 ;
memcpy ( res , " : \" " , 2 ) ;
res + = 2 ;
memcpy ( res , ZSTR_VAL ( Z_OBJCE_P ( struc ) - > name ) , ZSTR_LEN ( Z_OBJCE_P ( struc ) - > name ) ) ;
res + = ZSTR_LEN ( Z_OBJCE_P ( struc ) - > name ) ;
memcpy ( res , " \" : " , 2 ) ;
res + = 2 ;
memcpy ( res , s2 , l2 ) ;
res + = l2 ;
memcpy ( res , " :{ " , 2 ) ;
res + = 2 ;
memcpy ( res , ( char * ) serialized_data , serialized_length ) ;
res [ serialized_length ] = ' } ' ;
2005-02-23 11:17:52 +00:00
} else {
2019-02-21 11:04:49 +00:00
/* Mark this value in the var_hash, to avoid creating references to it. */
zval * var_idx = zend_hash_index_find ( & var_hash - > ht ,
( zend_ulong ) ( zend_uintptr_t ) Z_COUNTED_P ( struc ) ) ;
2021-02-26 10:30:19 +00:00
if ( var_idx ) {
ZVAL_LONG ( var_idx , - 1 ) ;
}
2005-02-23 11:17:52 +00:00
smart_str_appendl ( buf , " N; " , 2 ) ;
}
2007-11-02 19:40:39 +00:00
if ( serialized_data ) {
2005-02-23 11:17:52 +00:00
efree ( serialized_data ) ;
}
return ;
}
2007-11-02 19:40:39 +00:00
2021-02-25 09:16:22 +00:00
if ( ce ! = PHP_IC_ENTRY ) {
zval * zv = zend_hash_find_ex ( & ce - > function_table , ZSTR_KNOWN ( ZEND_STR_SLEEP ) , 1 ) ;
if ( zv ) {
zval retval , tmp ;
ZVAL_OBJ_COPY ( & tmp , Z_OBJ_P ( struc ) ) ;
if ( php_var_serialize_call_sleep ( Z_OBJ ( tmp ) , Z_FUNC_P ( zv ) , & retval ) = = FAILURE ) {
if ( ! EG ( exception ) ) {
/* we should still add element even if it's not OK,
* since we already wrote the length of the array before */
smart_str_appendl ( buf , " N; " , 2 ) ;
}
OBJ_RELEASE ( Z_OBJ ( tmp ) ) ;
return ;
2002-03-19 11:25:21 +00:00
}
2021-02-25 09:16:22 +00:00
php_var_serialize_class ( buf , & tmp , & retval , var_hash ) ;
zval_ptr_dtor ( & retval ) ;
OBJ_RELEASE ( Z_OBJ ( tmp ) ) ;
2007-11-02 19:40:39 +00:00
return ;
2000-03-16 02:15:41 +00:00
}
}
2007-11-02 19:40:39 +00:00
2014-12-13 22:06:14 +00:00
incomplete_class = php_var_serialize_class_name ( buf , struc ) ;
2021-03-01 13:10:56 +00:00
if ( Z_OBJ_P ( struc ) - > properties = = NULL
& & Z_OBJ_HT_P ( struc ) - > get_properties_for = = NULL
& & Z_OBJ_HT_P ( struc ) - > get_properties = = zend_std_get_properties ) {
/* Optimized version without rebulding properties HashTable */
zend_object * obj = Z_OBJ_P ( struc ) ;
zend_class_entry * ce = obj - > ce ;
zend_property_info * prop_info ;
zval * prop ;
int i ;
count = ce - > default_properties_count ;
for ( i = 0 ; i < ce - > default_properties_count ; i + + ) {
prop_info = ce - > properties_info_table [ i ] ;
if ( ! prop_info ) {
count - - ;
continue ;
}
prop = OBJ_PROP ( obj , prop_info - > offset ) ;
if ( Z_TYPE_P ( prop ) = = IS_UNDEF ) {
count - - ;
continue ;
}
}
if ( count ) {
smart_str_append_unsigned ( buf , count ) ;
smart_str_appendl ( buf , " :{ " , 2 ) ;
for ( i = 0 ; i < ce - > default_properties_count ; i + + ) {
prop_info = ce - > properties_info_table [ i ] ;
if ( ! prop_info ) {
continue ;
}
prop = OBJ_PROP ( obj , prop_info - > offset ) ;
if ( Z_TYPE_P ( prop ) = = IS_UNDEF ) {
continue ;
}
php_var_serialize_string ( buf , ZSTR_VAL ( prop_info - > name ) , ZSTR_LEN ( prop_info - > name ) ) ;
if ( Z_ISREF_P ( prop ) & & Z_REFCOUNT_P ( prop ) = = 1 ) {
prop = Z_REFVAL_P ( prop ) ;
}
php_var_serialize_intern ( buf , prop , var_hash ) ;
}
smart_str_appendc ( buf , ' } ' ) ;
} else {
smart_str_appendl ( buf , " 0:{} " , 4 ) ;
}
return ;
}
2018-10-04 11:58:35 +00:00
myht = zend_get_properties_for ( struc , ZEND_PROP_PURPOSE_SERIALIZE ) ;
2015-08-26 00:27:05 +00:00
/* count after serializing name, since php_var_serialize_class_name
* changes the count if the variable is incomplete class */
2020-01-02 09:43:01 +00:00
count = zend_array_count ( myht ) ;
if ( count > 0 & & incomplete_class ) {
- - count ;
2015-08-26 00:27:05 +00:00
}
2020-01-02 09:43:01 +00:00
php_var_serialize_nested_data ( buf , struc , myht , count , incomplete_class , var_hash ) ;
2018-10-04 11:58:35 +00:00
zend_release_properties ( myht ) ;
2020-01-02 09:43:01 +00:00
return ;
2018-10-04 11:58:35 +00:00
}
2020-01-02 09:43:01 +00:00
case IS_ARRAY :
smart_str_appendl ( buf , " a: " , 2 ) ;
myht = Z_ARRVAL_P ( struc ) ;
php_var_serialize_nested_data (
buf , struc , myht , zend_array_count ( myht ) , /* incomplete_class */ 0 , var_hash ) ;
1999-04-17 00:37:12 +00:00
return ;
2014-02-26 03:08:13 +00:00
case IS_REFERENCE :
struc = Z_REFVAL_P ( struc ) ;
goto again ;
1999-04-17 00:37:12 +00:00
default :
2001-08-03 07:25:27 +00:00
smart_str_appendl ( buf , " i:0; " , 4 ) ;
1999-04-17 00:37:12 +00:00
return ;
2007-11-02 19:40:39 +00:00
}
1999-04-17 00:37:12 +00:00
}
2007-11-02 19:40:39 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2014-12-13 22:06:14 +00:00
PHPAPI void php_var_serialize ( smart_str * buf , zval * struc , php_serialize_data_t * data ) /* { { { */
2001-08-03 11:00:16 +00:00
{
2014-12-13 22:06:14 +00:00
php_var_serialize_intern ( buf , struc , * data ) ;
2001-08-03 11:00:16 +00:00
smart_str_0 ( buf ) ;
}
1999-04-25 12:41:18 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2020-07-22 16:59:00 +00:00
PHPAPI php_serialize_data_t php_var_serialize_init ( void ) {
2016-08-10 10:51:48 +00:00
struct php_serialize_data * d ;
/* fprintf(stderr, "SERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */
if ( BG ( serialize_lock ) | | ! BG ( serialize ) . level ) {
d = emalloc ( sizeof ( struct php_serialize_data ) ) ;
zend_hash_init ( & d - > ht , 16 , NULL , ZVAL_PTR_DTOR , 0 ) ;
d - > n = 0 ;
if ( ! BG ( serialize_lock ) ) {
BG ( serialize ) . data = d ;
BG ( serialize ) . level = 1 ;
}
} else {
d = BG ( serialize ) . data ;
+ + BG ( serialize ) . level ;
}
return d ;
}
PHPAPI void php_var_serialize_destroy ( php_serialize_data_t d ) {
/* fprintf(stderr, "SERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */
if ( BG ( serialize_lock ) | | BG ( serialize ) . level = = 1 ) {
zend_hash_destroy ( & d - > ht ) ;
efree ( d ) ;
}
if ( ! BG ( serialize_lock ) & & ! - - BG ( serialize ) . level ) {
BG ( serialize ) . data = NULL ;
}
}
2020-07-01 13:32:55 +00:00
/* {{{ Returns a string representation of variable (which can later be unserialized) */
1999-04-17 00:37:12 +00:00
PHP_FUNCTION ( serialize )
{
2014-02-14 09:40:11 +00:00
zval * struc ;
2000-10-30 17:10:06 +00:00
php_serialize_data_t var_hash ;
2001-08-03 07:25:27 +00:00
smart_str buf = { 0 } ;
1999-04-17 00:37:12 +00:00
2016-12-31 02:03:33 +00:00
ZEND_PARSE_PARAMETERS_START ( 1 , 1 )
2017-06-19 09:55:59 +00:00
Z_PARAM_ZVAL ( struc )
2016-12-31 02:03:33 +00:00
ZEND_PARSE_PARAMETERS_END ( ) ;
2001-07-09 09:03:06 +00:00
2000-10-30 17:10:06 +00:00
PHP_VAR_SERIALIZE_INIT ( var_hash ) ;
2014-12-13 22:06:14 +00:00
php_var_serialize ( & buf , struc , & var_hash ) ;
2000-10-30 17:10:06 +00:00
PHP_VAR_SERIALIZE_DESTROY ( var_hash ) ;
2002-03-19 11:25:21 +00:00
2013-03-09 15:00:58 +00:00
if ( EG ( exception ) ) {
smart_str_free ( & buf ) ;
2020-01-03 19:44:29 +00:00
RETURN_THROWS ( ) ;
2013-03-09 15:00:58 +00:00
}
2014-02-18 09:42:46 +00:00
if ( buf . s ) {
2015-03-12 13:53:51 +00:00
RETURN_NEW_STR ( buf . s ) ;
2002-03-19 11:25:21 +00:00
} else {
2019-12-11 22:59:13 +00:00
RETURN_EMPTY_STRING ( ) ;
2002-03-19 11:25:21 +00:00
}
1999-04-17 00:37:12 +00:00
}
1999-04-25 12:41:18 +00:00
/* }}} */
2007-06-26 11:51:14 +00:00
2020-07-07 22:47:52 +00:00
/* {{{ Takes a string representation of variable and recreates it, subject to the optional unserialize options HashTable */
PHPAPI void php_unserialize_with_options ( zval * return_value , const char * buf , const size_t buf_len , HashTable * options , const char * function_name )
1999-04-17 00:37:12 +00:00
{
2006-07-10 14:02:40 +00:00
const unsigned char * p ;
2001-11-10 21:18:34 +00:00
php_unserialize_data_t var_hash ;
2016-10-23 19:37:36 +00:00
zval * retval ;
2016-09-06 10:59:35 +00:00
HashTable * class_hash = NULL , * prev_class_hash ;
2019-09-24 09:50:26 +00:00
zend_long prev_max_depth , prev_cur_depth ;
2007-11-02 19:40:39 +00:00
2006-07-10 14:02:40 +00:00
if ( buf_len = = 0 ) {
RETURN_FALSE ;
}
1999-09-15 11:42:28 +00:00
2007-11-02 19:40:39 +00:00
p = ( const unsigned char * ) buf ;
2006-07-10 14:02:40 +00:00
PHP_VAR_UNSERIALIZE_INIT ( var_hash ) ;
2016-09-06 10:59:35 +00:00
prev_class_hash = php_var_unserialize_get_allowed_classes ( var_hash ) ;
2019-09-24 09:50:26 +00:00
prev_max_depth = php_var_unserialize_get_max_depth ( var_hash ) ;
prev_cur_depth = php_var_unserialize_get_cur_depth ( var_hash ) ;
2016-09-06 10:59:35 +00:00
if ( options ! = NULL ) {
2019-09-24 09:50:26 +00:00
zval * classes , * max_depth ;
2020-07-07 22:47:52 +00:00
classes = zend_hash_str_find_deref ( options , " allowed_classes " , sizeof ( " allowed_classes " ) - 1 ) ;
2016-09-06 02:56:36 +00:00
if ( classes & & Z_TYPE_P ( classes ) ! = IS_ARRAY & & Z_TYPE_P ( classes ) ! = IS_TRUE & & Z_TYPE_P ( classes ) ! = IS_FALSE ) {
2020-09-10 11:28:18 +00:00
zend_type_error ( " %s(): Option \" allowed_classes \" must be of type array|bool, %s given " , function_name , zend_zval_type_name ( classes ) ) ;
2019-09-24 09:50:26 +00:00
goto cleanup ;
2016-09-06 02:56:36 +00:00
}
2014-12-13 22:06:14 +00:00
if ( classes & & ( Z_TYPE_P ( classes ) = = IS_ARRAY | | ! zend_is_true ( classes ) ) ) {
2013-03-30 04:52:48 +00:00
ALLOC_HASHTABLE ( class_hash ) ;
zend_hash_init ( class_hash , ( Z_TYPE_P ( classes ) = = IS_ARRAY ) ? zend_hash_num_elements ( Z_ARRVAL_P ( classes ) ) : 0 , NULL , NULL , 0 ) ;
}
if ( class_hash & & Z_TYPE_P ( classes ) = = IS_ARRAY ) {
zval * entry ;
zend_string * lcname ;
ZEND_HASH_FOREACH_VAL ( Z_ARRVAL_P ( classes ) , entry ) {
2021-01-14 11:06:07 +00:00
convert_to_string ( entry ) ;
2014-12-24 12:04:51 +00:00
lcname = zend_string_tolower ( Z_STR_P ( entry ) ) ;
2013-03-30 04:52:48 +00:00
zend_hash_add_empty_element ( class_hash , lcname ) ;
2018-05-28 13:27:12 +00:00
zend_string_release_ex ( lcname , 0 ) ;
2013-03-30 04:52:48 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2019-02-26 14:32:18 +00:00
/* Exception during string conversion. */
if ( EG ( exception ) ) {
2019-09-24 09:50:26 +00:00
goto cleanup ;
2019-02-26 14:32:18 +00:00
}
2013-03-30 04:52:48 +00:00
}
2016-09-06 02:56:36 +00:00
php_var_unserialize_set_allowed_classes ( var_hash , class_hash ) ;
2019-09-24 09:50:26 +00:00
2020-07-07 22:47:52 +00:00
max_depth = zend_hash_str_find_deref ( options , " max_depth " , sizeof ( " max_depth " ) - 1 ) ;
2019-09-24 09:50:26 +00:00
if ( max_depth ) {
if ( Z_TYPE_P ( max_depth ) ! = IS_LONG ) {
2020-09-10 11:28:18 +00:00
zend_type_error ( " %s(): Option \" max_depth \" must be of type int, %s given " , function_name , zend_zval_type_name ( max_depth ) ) ;
2019-09-24 09:50:26 +00:00
goto cleanup ;
}
if ( Z_LVAL_P ( max_depth ) < 0 ) {
2020-09-10 11:28:18 +00:00
zend_value_error ( " %s(): Option \" max_depth \" must be greater than or equal to 0 " , function_name ) ;
2019-09-24 09:50:26 +00:00
goto cleanup ;
}
php_var_unserialize_set_max_depth ( var_hash , Z_LVAL_P ( max_depth ) ) ;
/* If the max_depth for a nested unserialize() call has been overridden,
* start counting from zero again ( for the nested call only ) . */
php_var_unserialize_set_cur_depth ( var_hash , 0 ) ;
}
2013-03-30 04:52:48 +00:00
}
2018-12-12 17:04:36 +00:00
if ( BG ( unserialize ) . level > 1 ) {
retval = var_tmp_var ( & var_hash ) ;
} else {
retval = return_value ;
}
2016-11-05 22:10:19 +00:00
if ( ! php_var_unserialize ( retval , & p , p + buf_len , & var_hash ) ) {
2013-03-09 15:00:58 +00:00
if ( ! EG ( exception ) ) {
2016-02-14 13:02:19 +00:00
php_error_docref ( NULL , E_NOTICE , " Error at offset " ZEND_LONG_FMT " of %zd bytes " ,
( zend_long ) ( ( char * ) p - buf ) , buf_len ) ;
2013-03-09 15:00:58 +00:00
}
2018-12-12 17:04:36 +00:00
if ( BG ( unserialize ) . level < = 1 ) {
zval_ptr_dtor ( return_value ) ;
}
2016-09-06 10:59:35 +00:00
RETVAL_FALSE ;
2018-12-12 17:04:36 +00:00
} else if ( BG ( unserialize ) . level > 1 ) {
2016-11-05 22:10:19 +00:00
ZVAL_COPY ( return_value , retval ) ;
2018-12-12 17:04:36 +00:00
} else if ( Z_REFCOUNTED_P ( return_value ) ) {
zend_refcounted * ref = Z_COUNTED_P ( return_value ) ;
gc_check_possible_root ( ref ) ;
2016-04-10 11:01:54 +00:00
}
2019-09-24 09:50:26 +00:00
cleanup :
2016-04-07 11:28:54 +00:00
if ( class_hash ) {
2013-03-30 04:52:48 +00:00
zend_hash_destroy ( class_hash ) ;
FREE_HASHTABLE ( class_hash ) ;
}
2016-09-06 10:59:35 +00:00
2019-09-24 09:50:26 +00:00
/* Reset to previous options in case this is a nested call */
2016-09-06 10:59:35 +00:00
php_var_unserialize_set_allowed_classes ( var_hash , prev_class_hash ) ;
2019-09-24 09:50:26 +00:00
php_var_unserialize_set_max_depth ( var_hash , prev_max_depth ) ;
php_var_unserialize_set_cur_depth ( var_hash , prev_cur_depth ) ;
2016-09-06 10:59:35 +00:00
PHP_VAR_UNSERIALIZE_DESTROY ( var_hash ) ;
2017-10-17 10:25:19 +00:00
/* Per calling convention we must not return a reference here, so unwrap. We're doing this at
* the very end , because __wakeup ( ) calls performed during UNSERIALIZE_DESTROY might affect
* the value we unwrap here . This is compatible with behavior in PHP < = 7.0 . */
if ( Z_ISREF_P ( return_value ) ) {
zend_unwrap_reference ( return_value ) ;
}
1999-04-17 00:37:12 +00:00
}
1999-06-15 17:06:22 +00:00
/* }}} */
1999-04-25 12:41:18 +00:00
2020-07-07 22:47:52 +00:00
/* {{{ Takes a string representation of variable and recreates it */
PHP_FUNCTION ( unserialize )
{
char * buf = NULL ;
size_t buf_len ;
HashTable * options = NULL ;
ZEND_PARSE_PARAMETERS_START ( 1 , 2 )
Z_PARAM_STRING ( buf , buf_len )
Z_PARAM_OPTIONAL
Z_PARAM_ARRAY_HT ( options )
ZEND_PARSE_PARAMETERS_END ( ) ;
php_unserialize_with_options ( return_value , buf , buf_len , options , " unserialize " ) ;
}
/* }}} */
2020-07-01 13:32:55 +00:00
/* {{{ Returns the allocated by PHP memory */
2003-01-18 15:03:01 +00:00
PHP_FUNCTION ( memory_get_usage ) {
2021-01-15 11:30:54 +00:00
bool real_usage = 0 ;
2006-07-25 13:40:05 +00:00
2016-12-31 02:03:33 +00:00
ZEND_PARSE_PARAMETERS_START ( 0 , 1 )
Z_PARAM_OPTIONAL
Z_PARAM_BOOL ( real_usage )
2019-10-07 08:02:18 +00:00
ZEND_PARSE_PARAMETERS_END ( ) ;
2007-11-02 19:40:39 +00:00
2014-12-13 22:06:14 +00:00
RETURN_LONG ( zend_memory_usage ( real_usage ) ) ;
2003-01-14 18:26:47 +00:00
}
/* }}} */
2006-12-20 10:49:33 +00:00
2020-07-01 13:32:55 +00:00
/* {{{ Returns the peak allocated by PHP memory */
2006-05-30 14:51:20 +00:00
PHP_FUNCTION ( memory_get_peak_usage ) {
2021-01-15 11:30:54 +00:00
bool real_usage = 0 ;
2006-07-25 13:40:05 +00:00
2016-12-31 02:03:33 +00:00
ZEND_PARSE_PARAMETERS_START ( 0 , 1 )
Z_PARAM_OPTIONAL
Z_PARAM_BOOL ( real_usage )
2019-10-07 08:02:18 +00:00
ZEND_PARSE_PARAMETERS_END ( ) ;
2006-07-25 13:40:05 +00:00
2014-12-13 22:06:14 +00:00
RETURN_LONG ( zend_memory_peak_usage ( real_usage ) ) ;
2006-05-30 14:51:20 +00:00
}
/* }}} */
2019-09-24 09:50:26 +00:00
PHP_INI_BEGIN ( )
STD_PHP_INI_ENTRY ( " unserialize_max_depth " , " 4096 " , PHP_INI_ALL , OnUpdateLong , unserialize_max_depth , php_basic_globals , basic_globals )
PHP_INI_END ( )
PHP_MINIT_FUNCTION ( var )
{
REGISTER_INI_ENTRIES ( ) ;
return SUCCESS ;
}