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