@@ -57,7 +57,7 @@ ZEND_GET_MODULE(bz2)
5757
5858struct php_bz2_stream_data_t {
5959 BZFILE * bz_file ;
60- php_stream * stream ;
60+ zend_resource * stream_res ;
6161};
6262
6363/* {{{ BZip2 stream implementation */
@@ -129,8 +129,15 @@ static int php_bz2iop_close(php_stream *stream, int close_handle)
129129 BZ2_bzclose (self -> bz_file );
130130 }
131131
132- if (self -> stream ) {
133- php_stream_free (self -> stream , PHP_STREAM_FREE_CLOSE | (close_handle == 0 ? PHP_STREAM_FREE_PRESERVE_HANDLE : 0 ));
132+ /* The inner stream may have been closed by the user, only its resource is held */
133+ if (self -> stream_res ) {
134+ php_stream * inner = zend_fetch_resource2 (
135+ self -> stream_res , NULL , php_file_le_stream (), php_file_le_pstream ());
136+ if (inner ) {
137+ php_stream_free (inner , PHP_STREAM_FREE_CLOSE | (close_handle == 0 ? PHP_STREAM_FREE_PRESERVE_HANDLE : 0 ));
138+ } else {
139+ zend_list_delete (self -> stream_res );
140+ }
134141 }
135142
136143 efree (self );
@@ -156,15 +163,33 @@ const php_stream_ops php_stream_bz2io_ops = {
156163};
157164
158165/* {{{ Bzip2 stream openers */
166+
167+ /* bzlib closes the descriptor it is given, so it gets a duplicate */
168+ static BZFILE * php_bz2_bzdopen (php_socket_t fd , const char * mode )
169+ {
170+ int dup_fd = dup ((int ) fd );
171+ if (dup_fd == -1 ) {
172+ return NULL ;
173+ }
174+
175+ BZFILE * bz = BZ2_bzdopen (dup_fd , mode );
176+ if (!bz ) {
177+ close (dup_fd );
178+ }
179+
180+ return bz ;
181+ }
182+
159183PHP_BZ2_API php_stream * _php_stream_bz2open_from_BZFILE (BZFILE * bz ,
160184 const char * mode , php_stream * innerstream STREAMS_DC )
161185{
162186 struct php_bz2_stream_data_t * self ;
163187
164188 self = emalloc (sizeof (* self ));
165189
166- self -> stream = innerstream ;
190+ self -> stream_res = NULL ;
167191 if (innerstream ) {
192+ self -> stream_res = innerstream -> res ;
168193 GC_ADDREF (innerstream -> res );
169194 }
170195 self -> bz_file = bz ;
@@ -221,7 +246,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper,
221246 if (stream ) {
222247 php_socket_t fd ;
223248 if (SUCCESS == php_stream_cast (stream , PHP_STREAM_AS_FD , (void * * ) & fd , REPORT_ERRORS )) {
224- bz_file = BZ2_bzdopen (( int ) fd , mode );
249+ bz_file = php_bz2_bzdopen ( fd , mode );
225250 }
226251 }
227252
@@ -407,7 +432,10 @@ PHP_FUNCTION(bzopen)
407432 RETURN_FALSE ;
408433 }
409434
410- bz = BZ2_bzdopen ((int )fd , mode );
435+ bz = php_bz2_bzdopen (fd , mode );
436+ if (!bz ) {
437+ RETURN_FALSE ;
438+ }
411439
412440 stream = php_stream_bz2open_from_BZFILE (bz , mode , stream );
413441 } else {
0 commit comments