]> granicus.if.org Git - php/commitdiff
Hopefully fix resource usage so that we have no leaks and don't segfault.
authorWez Furlong <wez@php.net>
Sat, 16 Mar 2002 14:39:51 +0000 (14:39 +0000)
committerWez Furlong <wez@php.net>
Sat, 16 Mar 2002 14:39:51 +0000 (14:39 +0000)
ext/zlib/zlib_fopen_wrapper.c
main/main.c
main/network.c
main/php_streams.h
main/streams.c

index 061326816c29c1116ea1d9cdcc67e3e2ac8d9b44..31589f824b4e2ed3e17159f150b33fa81b713829 100644 (file)
@@ -32,7 +32,7 @@ static size_t php_gziop_read(php_stream *stream, char *buf, size_t count)
 {
        struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t *)stream->abstract;
 
-       if (buf == NULL && count == 0)  {
+       if (buf == NULL && count == 0) {
                if (gzeof(self->gz_file))
                        return EOF;
                return 0;
@@ -60,13 +60,14 @@ static int php_gziop_seek(php_stream *stream, off_t offset, int whence)
        return gzseek(self->gz_file, offset, whence);
 }
 
-static int php_gziop_close(php_stream *stream)
+static int php_gziop_close(php_stream *stream, int close_handle)
 {
        struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t *)stream->abstract;
        int ret;
        
-       ret = gzclose(self->gz_file);
-       php_stream_close(self->stream);
+       if (close_handle)
+               ret = gzclose(self->gz_file);
+       php_stream_free(self->stream, close_handle);
        efree(self);
 
        return ret;
@@ -92,9 +93,9 @@ php_stream *php_stream_gzopen(char *path, char *mode, int options, char **opened
        
        self->stream = php_stream_open_wrapper(path, mode, options, opened_path TSRMLS_CC);
        
-       if (self->stream)       {
+       if (self->stream) {
                int fd;
-               if (SUCCESS == php_stream_cast(self->stream, PHP_STREAM_AS_FD, (void**)&fd, REPORT_ERRORS))     {
+               if (SUCCESS == php_stream_cast(self->stream, PHP_STREAM_AS_FD, (void**)&fd, REPORT_ERRORS)) {
                        self->gz_file = gzdopen(fd, mode);
                        if (self->gz_file)      {
                                stream = php_stream_alloc(&php_stream_gzio_ops, self, 0, mode);
index e3faf52d881989635aefe0e16a9465d2fddee9a1..187286ad49d4c1c7f1d09f927b049197e5e09dbb 100644 (file)
@@ -572,11 +572,10 @@ static FILE *php_fopen_wrapper_for_zend(const char *filename, char **opened_path
                /* no need for us to check the stream type here */
                php_stream_sock_set_chunk_size(stream, 1);
 
-               if (php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void**)&retval, 1) == SUCCESS)     {
-                       /* The leak here prevents a segfault */
-                       /*      ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream()); */
-               }
-               else    {
+               /* when this succeeds, stream either has or will be freed automatically */
+               if (php_stream_cast(stream, PHP_STREAM_AS_STDIO|PHP_STREAM_CAST_TRY_HARD|PHP_STREAM_CAST_RELEASE,
+                                       (void**)&retval, REPORT_ERRORS) == FAILURE)
+               {
                        php_stream_close(stream);
                        if (opened_path && *opened_path)
                                efree(*opened_path);
index dd877bbd1dd2be5f11d606bc848543d5e246bc79..93e0f2bbceb7018482794b54785ed0c05f10d66c 100644 (file)
@@ -675,22 +675,24 @@ static size_t php_sockop_read(php_stream *stream, char *buf, size_t count)
        return ret;
 }
 
-static int php_sockop_close(php_stream *stream)
+static int php_sockop_close(php_stream *stream, int close_handle)
 {
        php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
 
+       if (close_handle) {
 #if HAVE_OPENSSL_EXT
-       if (sock->ssl_active)   {
-               SSL_shutdown(sock->ssl_handle);
-               sock->ssl_active = 0;
-               SSL_free(sock->ssl_handle);
-               sock->ssl_handle = NULL;
-       }
+               if (sock->ssl_active) {
+                       SSL_shutdown(sock->ssl_handle);
+                       sock->ssl_active = 0;
+                       SSL_free(sock->ssl_handle);
+                       sock->ssl_handle = NULL;
+               }
 #endif
-       
-       shutdown(sock->socket, 0);
-       closesocket(sock->socket);
 
+               shutdown(sock->socket, 0);
+               closesocket(sock->socket);
+
+       }
        if (sock->readbuf)
                pefree(sock->readbuf, php_stream_is_persistent(stream));
 
index 7ec7f6f6f7caaa2a3fdea39ccabd5e76ce41f628..65a83c803614a177ae8046ee34bdb782db3d50e0 100755 (executable)
@@ -43,7 +43,7 @@ typedef struct _php_stream_ops  {
        /* stdio like functions - these are mandatory! */
        size_t (*write)(php_stream *stream, const char *buf, size_t count);
        size_t (*read)(php_stream *stream, char *buf, size_t count);
-       int    (*close)(php_stream *stream);
+       int    (*close)(php_stream *stream, int close_handle);
        int    (*flush)(php_stream *stream);
        /* these are optional */
        int    (*seek)(php_stream *stream, off_t offset, int whence);
@@ -132,7 +132,8 @@ PHPAPI php_stream *php_stream_fopen_temporary_file(const char *dir, const char *
 
 /* try really, really hard to make sure the cast happens (socketpair) */
 #define PHP_STREAM_CAST_TRY_HARD       0x80000000
-
+#define PHP_STREAM_CAST_RELEASE                0x40000000      /* stream becomes invalid on success */
+#define PHP_STREAM_CAST_MASK           (PHP_STREAM_CAST_TRY_HARD | PHP_STREAM_CAST_RELEASE)
 PHPAPI int php_stream_cast(php_stream *stream, int castas, void **ret, int show_err);
 /* use this to check if a stream can be cast into another form */
 #define php_stream_can_cast(stream, as)        php_stream_cast(stream, as, NULL, 0)
index eb0c942f277636dbbdabf1be97cfac30912136e5..be5ae0812c1c637105665592d79530440cb6fcd2 100755 (executable)
@@ -69,6 +69,7 @@ PHPAPI int php_stream_free(php_stream *stream, int call_dtor) /* {{{ */
 
        if (stream->wrapper && stream->wrapper->destroy) {
                stream->wrapper->destroy(stream);
+               stream->wrapper = NULL;
        }
 
        if (call_dtor) {
@@ -84,9 +85,12 @@ PHPAPI int php_stream_free(php_stream *stream, int call_dtor) /* {{{ */
                }
                
                php_stream_flush(stream);
-               ret = stream->ops->close(stream);
-               stream->abstract = NULL;
+       }
+       
+       ret = stream->ops->close(stream, call_dtor);
+       stream->abstract = NULL;
        
+       if (call_dtor)  {       
                /* tidy up any FILE* that might have been fdopened */
                if (stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FDOPEN && stream->stdiocast) {
                        fclose(stream->stdiocast);
@@ -96,6 +100,7 @@ PHPAPI int php_stream_free(php_stream *stream, int call_dtor) /* {{{ */
 
        if (stream->wrapperdata) {
                FREE_ZVAL(stream->wrapperdata);
+               stream->wrapperdata = NULL;
        }
        pefree(stream, stream->is_persistent);
 
@@ -494,18 +499,22 @@ static size_t php_stdiop_read(php_stream *stream, char *buf, size_t count)
        return fread(buf, 1, count, data->file);
 }
 
-static int php_stdiop_close(php_stream *stream)
+static int php_stdiop_close(php_stream *stream, int close_handle)
 {
        int ret;
        php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
 
        assert(data != NULL);
 
-       if (data->is_pipe) {
-               ret = pclose(data->file);
-       } else {
-               ret = fclose(data->file);
+       if (close_handle) {
+               if (data->is_pipe) {
+                       ret = pclose(data->file);
+               } else {
+                       ret = fclose(data->file);
+               }
        }
+       else
+               ret = 0;
 
        efree(data);
        
@@ -759,16 +768,15 @@ static COOKIE_IO_FUNCTIONS_T stream_cookie_functions =
 
 PHPAPI int php_stream_cast(php_stream *stream, int castas, void **ret, int show_err) /* {{{ */
 {
+       int flags = castas & PHP_STREAM_CAST_MASK;
+       castas &= ~PHP_STREAM_CAST_MASK;
        
-       /* trying hard is not yet implemented */
-       castas &= ~PHP_STREAM_CAST_TRY_HARD;
-       
-       if (castas == PHP_STREAM_AS_STDIO)      {
-               if (stream->stdiocast)  {
+       if (castas == PHP_STREAM_AS_STDIO) {
+               if (stream->stdiocast) {
                        if (ret) {
                                *ret = stream->stdiocast;
                        }
-                       return SUCCESS;
+                       goto exit_success;
                }
 
                if (stream->ops->cast && stream->ops->cast(stream, castas, ret) == SUCCESS)
@@ -782,8 +790,8 @@ PHPAPI int php_stream_cast(php_stream *stream, int castas, void **ret, int show_
 
                *ret = fopencookie(stream, stream->mode, stream_cookie_functions);
 
-               if (*ret != NULL)       {
-                       stream->fclose_stdiocast = 1;
+               if (*ret != NULL) {
+                       stream->fclose_stdiocast = PHP_STREAM_FCLOSE_FOPENCOOKIE;
                        goto exit_success;
                }
 
@@ -807,7 +815,7 @@ PHPAPI int php_stream_cast(php_stream *stream, int castas, void **ret, int show_
 
 
 exit_fail:
-       if (show_err)   {
+       if (show_err) {
                /* these names depend on the values of the PHP_STREAM_AS_XXX defines in php_streams.h */
                static const char *cast_names[3] = {
                        "STDIO FILE*", "File Descriptor", "Socket Descriptor"
@@ -827,6 +835,19 @@ exit_success:
        if (castas == PHP_STREAM_AS_STDIO && ret)
                stream->stdiocast = *ret;
 
+       if (flags & PHP_STREAM_CAST_RELEASE) {
+               /* Something other than php_stream_close will be closing
+                * the underlying handle, so we should free the stream handle/data
+                * here now.  The stream may not be freed immediately (in the case
+                * of fopencookie), but the caller should still not touch their
+                * original stream pointer in any case. */
+               if (stream->fclose_stdiocast != PHP_STREAM_FCLOSE_FOPENCOOKIE) {
+                       /* ask the implementation to release resources other than
+                        * the underlying handle */
+                       php_stream_free(stream, 0);
+               }
+       }
+       
        return SUCCESS;
 
 } /* }}} */