@@ -69,6 +69,81 @@ zend_result zend_startup_builtin_functions(void) /* {{{ */
69
69
}
70
70
/* }}} */
71
71
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 (& 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
+
72
147
ZEND_FUNCTION (exit )
73
148
{
74
149
zend_string * str = NULL ;
0 commit comments