@@ -217,6 +217,7 @@ static zend_object *curl_create_object(zend_class_entry *class_type);
217217static void curl_free_obj (zend_object * object );
218218static HashTable * curl_get_gc (zend_object * object , zval * * table , int * n );
219219static zend_function * curl_get_constructor (zend_object * object );
220+ static zval * curl_write_property (zend_object * object , zend_string * name , zval * value , void * * cache_slot );
220221static zend_object * curl_clone_obj (zend_object * object );
221222php_curl * init_curl_handle_into_zval (zval * curl );
222223static inline zend_result build_mime_structure_from_hash (php_curl * ch , zval * zpostfields );
@@ -370,6 +371,7 @@ PHP_MINIT_FUNCTION(curl)
370371 curl_object_handlers .clone_obj = curl_clone_obj ;
371372 curl_object_handlers .cast_object = curl_cast_object ;
372373 curl_object_handlers .compare = zend_objects_not_comparable ;
374+ curl_object_handlers .write_property = curl_write_property ;
373375
374376 curl_multi_ce = register_class_CurlMultiHandle ();
375377 curl_multi_register_handlers ();
@@ -402,6 +404,48 @@ static zend_function *curl_get_constructor(zend_object *object) {
402404 return NULL ;
403405}
404406
407+ static zval * curl_write_property (zend_object * object , zend_string * name , zval * value , void * * cache_slot )
408+ {
409+ if (zend_string_equals_literal (name , "share" )) {
410+ zval old_value ;
411+ /* Backup the old value, because the reassignment in zend_std_write_property might
412+ * cause a previously attached share handle to become RC=0 and we need to detach
413+ * it first before we may destruct the PHP object. */
414+ ZVAL_COPY (& old_value , zend_std_read_property (object , name , BP_VAR_R , cache_slot , NULL ));
415+
416+ /* Call zend_std_write_property first to rely on its validation features (e.g. for types)
417+ * before actually attaching the handle in the curl API. */
418+ zval * result = zend_std_write_property (object , name , value , cache_slot );
419+
420+ CURLSH * sh ;
421+ switch (Z_TYPE_P (result )) {
422+ case IS_NULL :
423+ sh = NULL ;
424+ break ;
425+ case IS_OBJECT :
426+ ZEND_ASSERT (Z_OBJCE_P (result ) == curl_share_ce || Z_OBJCE_P (result ) == curl_share_persistent_ce );
427+ sh = Z_CURL_SHARE_P (result )-> share ;
428+ break ;
429+ EMPTY_SWITCH_DEFAULT_CASE ();
430+ }
431+
432+ if (curl_easy_setopt (curl_from_obj (object )-> cp , CURLOPT_SHARE , sh ) != CURLE_OK ) {
433+ /* If the new handle is rejected by curl, we restore the old PHP property. */
434+ zend_std_write_property (object , name , & old_value , cache_slot );
435+ zend_throw_error (NULL , "Failed to set share handle" );
436+ return & EG (error_zval );
437+ }
438+
439+ /* The old value is no longer attached to the underlying curl structures and
440+ * can safely be destructed. */
441+ zval_ptr_dtor (& old_value );
442+
443+ return result ;
444+ } else {
445+ return zend_std_write_property (object , name , value , cache_slot );
446+ }
447+ }
448+
405449static zend_object * curl_clone_obj (zend_object * object ) {
406450 php_curl * ch ;
407451 CURL * cp ;
@@ -2239,24 +2283,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
22392283
22402284 case CURLOPT_SHARE :
22412285 {
2242- if (Z_TYPE_P (zvalue ) != IS_OBJECT ) {
2243- break ;
2244- }
2245-
2246- if (Z_OBJCE_P (zvalue ) != curl_share_ce && Z_OBJCE_P (zvalue ) != curl_share_persistent_ce ) {
2247- break ;
2248- }
2249-
2250- php_curlsh * sh = Z_CURL_SHARE_P (zvalue );
2251-
2252- curl_easy_setopt (ch -> cp , CURLOPT_SHARE , sh -> share );
2253-
2254- if (ch -> share ) {
2255- OBJ_RELEASE (& ch -> share -> std );
2256- }
2257-
2258- GC_ADDREF (& sh -> std );
2259- ch -> share = sh ;
2286+ zend_update_property (ch -> std .ce , & ch -> std , "share" , strlen ("share" ), zvalue );
22602287 }
22612288 break ;
22622289
@@ -2858,10 +2885,6 @@ static void curl_free_obj(zend_object *object)
28582885 zval_ptr_dtor (& ch -> postfields );
28592886 zval_ptr_dtor (& ch -> private_data );
28602887
2861- if (ch -> share ) {
2862- OBJ_RELEASE (& ch -> share -> std );
2863- }
2864-
28652888 zend_object_std_dtor (& ch -> std );
28662889}
28672890/* }}} */
0 commit comments