@@ -2266,10 +2266,7 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert
2266
2266
phar -> is_temporary_alias = source -> is_temporary_alias ;
2267
2267
phar -> alias = source -> alias ;
2268
2268
2269
- if (Z_TYPE (source -> metadata ) != IS_UNDEF ) {
2270
- ZVAL_DUP (& phar -> metadata , & source -> metadata );
2271
- phar -> metadata_len = 0 ;
2272
- }
2269
+ phar_metadata_tracker_copy (& phar -> metadata_tracker , & source -> metadata_tracker , phar -> is_persistent );
2273
2270
2274
2271
/* first copy each file's uncompressed contents to a temporary file and set per-file flags */
2275
2272
ZEND_HASH_FOREACH_PTR (& source -> manifest , entry ) {
@@ -2286,8 +2283,6 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert
2286
2283
goto no_copy ;
2287
2284
}
2288
2285
2289
- newentry .metadata_str .s = NULL ;
2290
-
2291
2286
if (FAILURE == phar_copy_file_contents (& newentry , phar -> fp )) {
2292
2287
zend_hash_destroy (& (phar -> manifest ));
2293
2288
php_stream_close (phar -> fp );
@@ -2298,10 +2293,7 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert
2298
2293
no_copy :
2299
2294
newentry .filename = estrndup (newentry .filename , newentry .filename_len );
2300
2295
2301
- if (Z_TYPE (newentry .metadata ) != IS_UNDEF ) {
2302
- zval_copy_ctor (& newentry .metadata );
2303
- newentry .metadata_str .s = NULL ;
2304
- }
2296
+ phar_metadata_tracker_clone (& newentry .metadata_tracker );
2305
2297
2306
2298
newentry .is_zip = phar -> is_zip ;
2307
2299
newentry .is_tar = phar -> is_tar ;
@@ -3444,10 +3436,7 @@ PHP_METHOD(Phar, copy)
3444
3436
3445
3437
memcpy ((void * ) & newentry , oldentry , sizeof (phar_entry_info ));
3446
3438
3447
- if (Z_TYPE (newentry .metadata ) != IS_UNDEF ) {
3448
- zval_copy_ctor (& newentry .metadata );
3449
- newentry .metadata_str .s = NULL ;
3450
- }
3439
+ phar_metadata_tracker_clone (& newentry .metadata_tracker );
3451
3440
3452
3441
newentry .filename = estrndup (newfile , newfile_len );
3453
3442
newentry .filename_len = newfile_len ;
@@ -3951,28 +3940,25 @@ PHP_METHOD(Phar, hasMetadata)
3951
3940
RETURN_THROWS ();
3952
3941
}
3953
3942
3954
- RETURN_BOOL (Z_TYPE ( phar_obj -> archive -> metadata ) != IS_UNDEF );
3943
+ RETURN_BOOL (phar_metadata_tracker_has_data ( & phar_obj -> archive -> metadata_tracker , phar_obj -> archive -> is_persistent ) );
3955
3944
}
3956
3945
/* }}} */
3957
3946
3958
3947
/* {{{ Returns the global metadata of the phar */
3959
3948
PHP_METHOD (Phar , getMetadata )
3960
3949
{
3950
+ zval * unserialize_options = NULL ;
3951
+ phar_metadata_tracker * tracker ;
3961
3952
PHAR_ARCHIVE_OBJECT ();
3962
3953
3963
- if (zend_parse_parameters_none () == FAILURE ) {
3964
- RETURN_THROWS ();
3965
- }
3954
+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
3955
+ Z_PARAM_OPTIONAL
3956
+ Z_PARAM_ARRAY (unserialize_options )
3957
+ ZEND_PARSE_PARAMETERS_END ();
3966
3958
3967
- if (Z_TYPE (phar_obj -> archive -> metadata ) != IS_UNDEF ) {
3968
- if (phar_obj -> archive -> is_persistent ) {
3969
- char * buf = estrndup ((char * ) Z_PTR (phar_obj -> archive -> metadata ), phar_obj -> archive -> metadata_len );
3970
- /* assume success, we would have failed before */
3971
- phar_parse_metadata (& buf , return_value , phar_obj -> archive -> metadata_len );
3972
- efree (buf );
3973
- } else {
3974
- ZVAL_COPY (return_value , & phar_obj -> archive -> metadata );
3975
- }
3959
+ tracker = & phar_obj -> archive -> metadata_tracker ;
3960
+ if (phar_metadata_tracker_has_data (tracker , phar_obj -> archive -> is_persistent )) {
3961
+ phar_metadata_tracker_unserialize_or_copy (tracker , return_value , phar_obj -> archive -> is_persistent , unserialize_options , "Phar::getMetadata" );
3976
3962
}
3977
3963
}
3978
3964
/* }}} */
@@ -3982,6 +3968,8 @@ PHP_METHOD(Phar, setMetadata)
3982
3968
{
3983
3969
char * error ;
3984
3970
zval * metadata ;
3971
+ php_serialize_data_t metadata_hash ;
3972
+ smart_str main_metadata_str = {0 };
3985
3973
3986
3974
PHAR_ARCHIVE_OBJECT ();
3987
3975
@@ -3998,12 +3986,24 @@ PHP_METHOD(Phar, setMetadata)
3998
3986
zend_throw_exception_ex (phar_ce_PharException , 0 , "phar \"%s\" is persistent, unable to copy on write" , phar_obj -> archive -> fname );
3999
3987
RETURN_THROWS ();
4000
3988
}
4001
- if (Z_TYPE (phar_obj -> archive -> metadata ) != IS_UNDEF ) {
4002
- zval_ptr_dtor (& phar_obj -> archive -> metadata );
4003
- ZVAL_UNDEF (& phar_obj -> archive -> metadata );
3989
+
3990
+ ZEND_ASSERT (!phar_obj -> archive -> is_persistent ); /* Should no longer be persistent */
3991
+
3992
+ phar_metadata_tracker_free (& phar_obj -> archive -> metadata_tracker , phar_obj -> archive -> is_persistent );
3993
+ if (EG (exception )) {
3994
+ /* Destructor can throw. */
3995
+ return ;
4004
3996
}
4005
3997
4006
- ZVAL_COPY (& phar_obj -> archive -> metadata , metadata );
3998
+ PHP_VAR_SERIALIZE_INIT (metadata_hash );
3999
+ php_var_serialize (& main_metadata_str , metadata , & metadata_hash );
4000
+ PHP_VAR_SERIALIZE_DESTROY (metadata_hash );
4001
+ if (EG (exception )) {
4002
+ /* Serialization can throw. Don't overwrite the original string. */
4003
+ return ;
4004
+ }
4005
+ ZVAL_COPY (& phar_obj -> archive -> metadata_tracker .val , metadata );
4006
+ phar_obj -> archive -> metadata_tracker .str = main_metadata_str .s ;
4007
4007
phar_obj -> archive -> is_modified = 1 ;
4008
4008
phar_flush (phar_obj -> archive , 0 , 0 , 0 , & error );
4009
4009
@@ -4030,20 +4030,18 @@ PHP_METHOD(Phar, delMetadata)
4030
4030
RETURN_THROWS ();
4031
4031
}
4032
4032
4033
- if (Z_TYPE (phar_obj -> archive -> metadata ) != IS_UNDEF ) {
4034
- zval_ptr_dtor (& phar_obj -> archive -> metadata );
4035
- ZVAL_UNDEF (& phar_obj -> archive -> metadata );
4036
- phar_obj -> archive -> is_modified = 1 ;
4037
- phar_flush (phar_obj -> archive , 0 , 0 , 0 , & error );
4033
+ if (!phar_metadata_tracker_has_data (& phar_obj -> archive -> metadata_tracker , phar_obj -> archive -> is_persistent )) {
4034
+ RETURN_TRUE ;
4035
+ }
4038
4036
4039
- if (error ) {
4040
- zend_throw_exception_ex (phar_ce_PharException , 0 , "%s" , error );
4041
- efree (error );
4042
- RETURN_THROWS ();
4043
- } else {
4044
- RETURN_TRUE ;
4045
- }
4037
+ phar_metadata_tracker_free (& phar_obj -> archive -> metadata_tracker , phar_obj -> archive -> is_persistent );
4038
+ phar_obj -> archive -> is_modified = 1 ;
4039
+ phar_flush (phar_obj -> archive , 0 , 0 , 0 , & error );
4046
4040
4041
+ if (error ) {
4042
+ zend_throw_exception_ex (phar_ce_PharException , 0 , "%s" , error );
4043
+ efree (error );
4044
+ RETURN_THROWS ();
4047
4045
} else {
4048
4046
RETURN_TRUE ;
4049
4047
}
@@ -4630,28 +4628,25 @@ PHP_METHOD(PharFileInfo, hasMetadata)
4630
4628
RETURN_THROWS ();
4631
4629
}
4632
4630
4633
- RETURN_BOOL (Z_TYPE ( entry_obj -> entry -> metadata ) != IS_UNDEF );
4631
+ RETURN_BOOL (phar_metadata_tracker_has_data ( & entry_obj -> entry -> metadata_tracker , entry_obj -> entry -> is_persistent ) );
4634
4632
}
4635
4633
/* }}} */
4636
4634
4637
4635
/* {{{ Returns the metadata of the entry */
4638
4636
PHP_METHOD (PharFileInfo , getMetadata )
4639
4637
{
4638
+ zval * unserialize_options = NULL ;
4639
+ phar_metadata_tracker * tracker ;
4640
4640
PHAR_ENTRY_OBJECT ();
4641
4641
4642
- if (zend_parse_parameters_none () == FAILURE ) {
4643
- RETURN_THROWS ();
4644
- }
4642
+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
4643
+ Z_PARAM_OPTIONAL
4644
+ Z_PARAM_ARRAY (unserialize_options )
4645
+ ZEND_PARSE_PARAMETERS_END ();
4645
4646
4646
- if (Z_TYPE (entry_obj -> entry -> metadata ) != IS_UNDEF ) {
4647
- if (entry_obj -> entry -> is_persistent ) {
4648
- char * buf = estrndup ((char * ) Z_PTR (entry_obj -> entry -> metadata ), entry_obj -> entry -> metadata_len );
4649
- /* assume success, we would have failed before */
4650
- phar_parse_metadata (& buf , return_value , entry_obj -> entry -> metadata_len );
4651
- efree (buf );
4652
- } else {
4653
- ZVAL_COPY (return_value , & entry_obj -> entry -> metadata );
4654
- }
4647
+ tracker = & entry_obj -> entry -> metadata_tracker ;
4648
+ if (phar_metadata_tracker_has_data (tracker , entry_obj -> entry -> is_persistent )) {
4649
+ phar_metadata_tracker_unserialize_or_copy (tracker , return_value , entry_obj -> entry -> is_persistent , unserialize_options , "PharFileInfo::getMetadata" );
4655
4650
}
4656
4651
}
4657
4652
/* }}} */
@@ -4689,12 +4684,9 @@ PHP_METHOD(PharFileInfo, setMetadata)
4689
4684
/* re-populate after copy-on-write */
4690
4685
entry_obj -> entry = zend_hash_str_find_ptr (& phar -> manifest , entry_obj -> entry -> filename , entry_obj -> entry -> filename_len );
4691
4686
}
4692
- if (Z_TYPE (entry_obj -> entry -> metadata ) != IS_UNDEF ) {
4693
- zval_ptr_dtor (& entry_obj -> entry -> metadata );
4694
- ZVAL_UNDEF (& entry_obj -> entry -> metadata );
4695
- }
4687
+ phar_metadata_tracker_free (& entry_obj -> entry -> metadata_tracker , entry_obj -> entry -> is_persistent );
4696
4688
4697
- ZVAL_COPY (& entry_obj -> entry -> metadata , metadata );
4689
+ ZVAL_COPY (& entry_obj -> entry -> metadata_tracker . val , metadata );
4698
4690
4699
4691
entry_obj -> entry -> is_modified = 1 ;
4700
4692
entry_obj -> entry -> phar -> is_modified = 1 ;
@@ -4729,7 +4721,7 @@ PHP_METHOD(PharFileInfo, delMetadata)
4729
4721
RETURN_THROWS ();
4730
4722
}
4731
4723
4732
- if (Z_TYPE ( entry_obj -> entry -> metadata ) != IS_UNDEF ) {
4724
+ if (phar_metadata_tracker_has_data ( & entry_obj -> entry -> metadata_tracker , entry_obj -> entry -> is_persistent ) ) {
4733
4725
if (entry_obj -> entry -> is_persistent ) {
4734
4726
phar_archive_data * phar = entry_obj -> entry -> phar ;
4735
4727
@@ -4740,8 +4732,8 @@ PHP_METHOD(PharFileInfo, delMetadata)
4740
4732
/* re-populate after copy-on-write */
4741
4733
entry_obj -> entry = zend_hash_str_find_ptr (& phar -> manifest , entry_obj -> entry -> filename , entry_obj -> entry -> filename_len );
4742
4734
}
4743
- zval_ptr_dtor ( & entry_obj -> entry -> metadata );
4744
- ZVAL_UNDEF (& entry_obj -> entry -> metadata );
4735
+ /* multiple values may reference the metadata */
4736
+ phar_metadata_tracker_free (& entry_obj -> entry -> metadata_tracker , entry_obj -> entry -> is_persistent );
4745
4737
entry_obj -> entry -> is_modified = 1 ;
4746
4738
entry_obj -> entry -> phar -> is_modified = 1 ;
4747
4739
0 commit comments