@@ -121,9 +121,32 @@ PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream *
121
121
if (zend_hash_find (& EG (persistent_list ), (char * )persistent_id , strlen (persistent_id )+ 1 , (void * ) & le ) == SUCCESS ) {
122
122
if (Z_TYPE_P (le ) == le_pstream ) {
123
123
if (stream ) {
124
+ HashPosition pos ;
125
+ zend_rsrc_list_entry * regentry ;
126
+ ulong index = -1 ; /* intentional */
127
+
128
+ /* see if this persistent resource already has been loaded to the
129
+ * regular list; allowing the same resource in several entries in the
130
+ * regular list causes trouble (see bug #54623) */
131
+ zend_hash_internal_pointer_reset_ex (& EG (regular_list ), & pos );
132
+ while (zend_hash_get_current_data_ex (& EG (regular_list ),
133
+ (void * * )& regentry , & pos ) == SUCCESS ) {
134
+ if (regentry -> ptr == le -> ptr ) {
135
+ zend_hash_get_current_key_ex (& EG (regular_list ), NULL , NULL ,
136
+ & index , 0 , & pos );
137
+ break ;
138
+ }
139
+ zend_hash_move_forward_ex (& EG (regular_list ), & pos );
140
+ }
141
+
124
142
* stream = (php_stream * )le -> ptr ;
125
- le -> refcount ++ ;
126
- (* stream )-> rsrc_id = ZEND_REGISTER_RESOURCE (NULL , * stream , le_pstream );
143
+ if (index == -1 ) { /* not found in regular list */
144
+ le -> refcount ++ ;
145
+ (* stream )-> rsrc_id = ZEND_REGISTER_RESOURCE (NULL , * stream , le_pstream );
146
+ } else {
147
+ regentry -> refcount ++ ;
148
+ (* stream )-> rsrc_id = index ;
149
+ }
127
150
}
128
151
return PHP_STREAM_PERSISTENT_SUCCESS ;
129
152
}
@@ -480,7 +503,7 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov
480
503
stream -> orig_path = NULL ;
481
504
}
482
505
483
- # if defined(PHP_WIN32 )
506
+ # if defined(PHP_WIN32_ )
484
507
OutputDebugString (leakinfo );
485
508
# else
486
509
fprintf (stderr , "%s" , leakinfo );
0 commit comments