@@ -254,44 +254,59 @@ ZEND_API void zend_clear_exception(void) /* {{{ */
254254}
255255/* }}} */
256256
257- /* Same as OBJ_PROP_NUM(), but checks the offset is correct when Zend is built in debug mode. */
258- static zend_always_inline zval * zend_obj_prop_num_checked (zend_object * object , uint32_t prop_num , zend_string * str )
257+ /* Same as writing to OBJ_PROP_NUM() when there are no hooks,
258+ * but checks the offset is correct when Zend is built in debug mode.
259+ * This is faster than going through the regular property write routine when the offset is known at compile time. */
260+ static void zend_update_property_num_checked (zend_object * object , uint32_t prop_num , zend_string * member , zval * value )
259261{
262+ if (UNEXPECTED (object -> ce -> num_hooked_props > 0 )) {
263+ /* Property may have been overridden with a hook. */
264+ zend_update_property_ex (object -> ce , object , member , value );
265+ zval_ptr_dtor (value );
266+ return ;
267+ }
260268#if ZEND_DEBUG
261269 zend_class_entry * old_scope = EG (fake_scope );
262270 EG (fake_scope ) = i_get_exception_base (object );
263- const zend_property_info * prop_info = zend_get_property_info (object -> ce , str , true);
271+ const zend_property_info * prop_info = zend_get_property_info (object -> ce , member , true);
264272 ZEND_ASSERT (OBJ_PROP_TO_NUM (prop_info -> offset ) == prop_num );
265273 EG (fake_scope ) = old_scope ;
266- #else
267- ZEND_IGNORE_VALUE (str );
268274#endif
269- return OBJ_PROP_NUM (object , prop_num );
275+ zval * zv = OBJ_PROP_NUM (object , prop_num );
276+ zval_ptr_safe_dtor (zv );
277+ ZVAL_COPY_VALUE (zv , value );
270278}
271279
272280static zend_object * zend_default_exception_new (zend_class_entry * class_type ) /* {{{ */
273281{
282+ zval tmp ;
283+ zval trace ;
274284 zend_string * filename ;
275285
276286 zend_object * object = zend_objects_new (class_type );
277287 object_properties_init (object , class_type );
278- zval * trace = zend_obj_prop_num_checked (object , 5 , ZSTR_KNOWN (ZEND_STR_TRACE ));
279288
280289 if (EG (current_execute_data )) {
281- zend_fetch_debug_backtrace (trace ,
290+ zend_fetch_debug_backtrace (& trace ,
282291 0 ,
283292 EG (exception_ignore_args ) ? DEBUG_BACKTRACE_IGNORE_ARGS : 0 , 0 );
284293 } else {
285- ZVAL_EMPTY_ARRAY (trace );
294+ ZVAL_EMPTY_ARRAY (& trace );
286295 }
287296
297+ zend_update_property_num_checked (object , 5 , ZSTR_KNOWN (ZEND_STR_TRACE ), & trace );
298+
288299 if (EXPECTED ((class_type != zend_ce_parse_error && class_type != zend_ce_compile_error )
289300 || !(filename = zend_get_compiled_filename ()))) {
290- ZVAL_STRING (zend_obj_prop_num_checked (object , 3 , ZSTR_KNOWN (ZEND_STR_FILE )), zend_get_executed_filename ());
291- ZVAL_LONG (zend_obj_prop_num_checked (object , 4 , ZSTR_KNOWN (ZEND_STR_LINE )), zend_get_executed_lineno ());
301+ ZVAL_STRING (& tmp , zend_get_executed_filename ());
302+ zend_update_property_num_checked (object , 3 , ZSTR_KNOWN (ZEND_STR_FILE ), & tmp );
303+ ZVAL_LONG (& tmp , zend_get_executed_lineno ());
304+ zend_update_property_num_checked (object , 4 , ZSTR_KNOWN (ZEND_STR_LINE ), & tmp );
292305 } else {
293- ZVAL_STR_COPY (zend_obj_prop_num_checked (object , 3 , ZSTR_KNOWN (ZEND_STR_FILE )), filename );
294- ZVAL_LONG (zend_obj_prop_num_checked (object , 4 , ZSTR_KNOWN (ZEND_STR_LINE )), zend_get_compiled_lineno ());
306+ ZVAL_STR_COPY (& tmp , filename );
307+ zend_update_property_num_checked (object , 3 , ZSTR_KNOWN (ZEND_STR_FILE ), & tmp );
308+ ZVAL_LONG (& tmp , zend_get_compiled_lineno ());
309+ zend_update_property_num_checked (object , 4 , ZSTR_KNOWN (ZEND_STR_LINE ), & tmp );
295310 }
296311
297312 return object ;
@@ -311,7 +326,7 @@ ZEND_METHOD(Exception, __construct)
311326{
312327 zend_string * message = NULL ;
313328 zend_long code = 0 ;
314- zval * object , * previous = NULL ;
329+ zval tmp , * object , * previous = NULL ;
315330
316331 object = ZEND_THIS ;
317332
@@ -320,21 +335,18 @@ ZEND_METHOD(Exception, __construct)
320335 }
321336
322337 if (message ) {
323- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 0 , ZSTR_KNOWN (ZEND_STR_MESSAGE ));
324- zval_ptr_safe_dtor (tmp );
325- ZVAL_STR_COPY (tmp , message );
338+ ZVAL_STR_COPY (& tmp , message );
339+ zend_update_property_num_checked (Z_OBJ_P (object ), 0 , ZSTR_KNOWN (ZEND_STR_MESSAGE ), & tmp );
326340 }
327341
328342 if (code ) {
329- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 2 , ZSTR_KNOWN (ZEND_STR_CODE ));
330- zval_ptr_dtor (tmp );
331- ZVAL_LONG (tmp , code );
343+ ZVAL_LONG (& tmp , code );
344+ zend_update_property_num_checked (Z_OBJ_P (object ), 2 , ZSTR_KNOWN (ZEND_STR_CODE ), & tmp );
332345 }
333346
334347 if (previous ) {
335- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 6 , ZSTR_KNOWN (ZEND_STR_PREVIOUS ));
336- zval_ptr_safe_dtor (tmp );
337- ZVAL_COPY (tmp , previous );
348+ Z_ADDREF_P (previous );
349+ zend_update_property_num_checked (Z_OBJ_P (object ), 6 , ZSTR_KNOWN (ZEND_STR_PREVIOUS ), previous );
338350 }
339351}
340352/* }}} */
@@ -364,7 +376,7 @@ ZEND_METHOD(ErrorException, __construct)
364376 zend_string * message = NULL , * filename = NULL ;
365377 zend_long code = 0 , severity = E_ERROR , lineno ;
366378 bool lineno_is_null = 1 ;
367- zval * object , * previous = NULL ;
379+ zval tmp , * object , * previous = NULL ;
368380
369381 if (zend_parse_parameters (ZEND_NUM_ARGS (), "|SllS!l!O!" , & message , & code , & severity , & filename , & lineno , & lineno_is_null , & previous , zend_ce_throwable ) == FAILURE ) {
370382 RETURN_THROWS ();
@@ -373,41 +385,34 @@ ZEND_METHOD(ErrorException, __construct)
373385 object = ZEND_THIS ;
374386
375387 if (message ) {
376- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 0 , ZSTR_KNOWN (ZEND_STR_MESSAGE ));
377- zval_ptr_safe_dtor (tmp );
378- ZVAL_STR_COPY (tmp , message );
388+ ZVAL_STR_COPY (& tmp , message );
389+ zend_update_property_num_checked (Z_OBJ_P (object ), 0 , ZSTR_KNOWN (ZEND_STR_MESSAGE ), & tmp );
379390 }
380391
381392 if (code ) {
382- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 2 , ZSTR_KNOWN (ZEND_STR_CODE ));
383- zval_ptr_dtor (tmp );
384- ZVAL_LONG (tmp , code );
393+ ZVAL_LONG (& tmp , code );
394+ zend_update_property_num_checked (Z_OBJ_P (object ), 2 , ZSTR_KNOWN (ZEND_STR_CODE ), & tmp );
385395 }
386396
387397 if (previous ) {
388- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 6 , ZSTR_KNOWN (ZEND_STR_PREVIOUS ));
389- zval_ptr_safe_dtor (tmp );
390- ZVAL_COPY (tmp , previous );
398+ Z_ADDREF_P (previous );
399+ zend_update_property_num_checked (Z_OBJ_P (object ), 6 , ZSTR_KNOWN (ZEND_STR_PREVIOUS ), previous );
391400 }
392401
393- {
394- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 7 , ZSTR_KNOWN (ZEND_STR_SEVERITY ));
395- zval_ptr_dtor (tmp );
396- ZVAL_LONG (tmp , severity );
397- }
402+ ZVAL_LONG (& tmp , severity );
403+ zend_update_property_num_checked (Z_OBJ_P (object ), 7 , ZSTR_KNOWN (ZEND_STR_SEVERITY ), & tmp );
398404
399405 if (filename ) {
400- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 3 , ZSTR_KNOWN (ZEND_STR_FILE ));
401- zval_ptr_dtor (tmp );
402- ZVAL_STR_COPY (tmp , filename );
406+ ZVAL_STR_COPY (& tmp , filename );
407+ zend_update_property_num_checked (Z_OBJ_P (object ), 3 , ZSTR_KNOWN (ZEND_STR_FILE ), & tmp );
403408 }
404409
405- zval * tmp = zend_obj_prop_num_checked (Z_OBJ_P (object ), 4 , ZSTR_KNOWN (ZEND_STR_LINE ));
406- zval_ptr_dtor (tmp );
407410 if (!lineno_is_null ) {
408- ZVAL_LONG (tmp , lineno );
411+ ZVAL_LONG (& tmp , lineno );
412+ zend_update_property_num_checked (Z_OBJ_P (object ), 4 , ZSTR_KNOWN (ZEND_STR_LINE ), & tmp );
409413 } else if (filename ) {
410- ZVAL_LONG (tmp , 0 );
414+ ZVAL_LONG (& tmp , 0 );
415+ zend_update_property_num_checked (Z_OBJ_P (object ), 4 , ZSTR_KNOWN (ZEND_STR_LINE ), & tmp );
411416 }
412417}
413418/* }}} */
0 commit comments