@@ -69,6 +69,81 @@ zend_result zend_startup_builtin_functions(void) /* {{{ */
6969}
7070/* }}} */
7171
72+ ZEND_FUNCTION (clone )
73+ {
74+ zend_object * zobj ;
75+ zval * args ;
76+ uint32_t argc ;
77+ HashTable * named_params ;
78+
79+ ZEND_PARSE_PARAMETERS_START (1 , -1 )
80+ Z_PARAM_OBJ (zobj )
81+ Z_PARAM_VARIADIC_WITH_NAMED (args , argc , named_params );
82+ ZEND_PARSE_PARAMETERS_END ();
83+
84+ zend_class_entry * scope = zend_get_executed_scope ();
85+
86+ zend_class_entry * ce = zobj -> ce ;
87+ zend_function * clone = ce -> clone ;
88+
89+ if (UNEXPECTED (zobj -> handlers -> clone_obj == NULL )) {
90+ zend_throw_error (NULL , "Trying to clone an uncloneable object of class %s" , ZSTR_VAL (ce -> name ));
91+ RETURN_THROWS ();
92+ }
93+
94+ if (clone && !(clone -> common .fn_flags & ZEND_ACC_PUBLIC )) {
95+ if (clone -> common .scope != scope ) {
96+ if (UNEXPECTED (clone -> common .fn_flags & ZEND_ACC_PRIVATE )
97+ || UNEXPECTED (!zend_check_protected (zend_get_function_root_class (clone ), scope ))) {
98+ zend_throw_error (NULL , "Call to %s %s::__clone() from %s%s" ,
99+ zend_visibility_string (clone -> common .fn_flags ), ZSTR_VAL (clone -> common .scope -> name ),
100+ scope ? "scope " : "global scope" ,
101+ scope ? ZSTR_VAL (scope -> name ) : ""
102+ );
103+ RETURN_THROWS ();
104+ }
105+ }
106+ }
107+
108+ zend_object * cloned ;
109+ if (zobj -> handlers -> clone_obj_with ) {
110+ if (UNEXPECTED (argc > 0 )) {
111+ HashTable params ;
112+ zend_hash_init (& params , argc + (named_params ? zend_hash_num_elements (named_params ) : 0 ), NULL , NULL , false);
113+ for (uint32_t i = 0 ; i < argc ; i ++ ) {
114+ zend_hash_index_add_new (& params , i , & args [i ]);
115+ }
116+ if (named_params != NULL ) {
117+ zend_string * key ;
118+ zval * val ;
119+ ZEND_HASH_FOREACH_STR_KEY_VAL (named_params , key , val ) {
120+ zend_hash_update (& params , key , val );
121+ } ZEND_HASH_FOREACH_END ();
122+ }
123+ cloned = zobj -> handlers -> clone_obj_with (zobj , scope , & params );
124+ zend_hash_destroy (& params );
125+ } else {
126+ cloned = zobj -> handlers -> clone_obj_with (zobj , scope , named_params );
127+ }
128+ } else {
129+ if (UNEXPECTED (named_params || argc > 0 )) {
130+ zend_throw_error (NULL , "Trying to clone an object with updated properties that is not compatible %s" , ZSTR_VAL (ce -> name ));
131+ RETURN_THROWS ();
132+ }
133+ cloned = zobj -> handlers -> clone_obj (zobj );
134+ }
135+
136+ if (EG (exception )) {
137+ if (cloned ) {
138+ OBJ_RELEASE (cloned );
139+ }
140+
141+ RETURN_THROWS ();
142+ }
143+
144+ RETURN_OBJ (cloned );
145+ }
146+
72147ZEND_FUNCTION (exit )
73148{
74149 zend_string * str = NULL ;
0 commit comments