mirror of
https://github.com/php/php-src.git
synced 2025-08-16 22:18:50 +02:00
Hopefully fix resource usage so that we have no leaks and don't segfault.
This commit is contained in:
parent
6abd7c6f93
commit
bed04279c3
5 changed files with 63 additions and 39 deletions
|
@ -60,13 +60,14 @@ static int php_gziop_seek(php_stream *stream, off_t offset, int whence)
|
||||||
return gzseek(self->gz_file, offset, 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;
|
struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t *)stream->abstract;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (close_handle)
|
||||||
ret = gzclose(self->gz_file);
|
ret = gzclose(self->gz_file);
|
||||||
php_stream_close(self->stream);
|
php_stream_free(self->stream, close_handle);
|
||||||
efree(self);
|
efree(self);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -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 */
|
/* no need for us to check the stream type here */
|
||||||
php_stream_sock_set_chunk_size(stream, 1);
|
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) {
|
/* when this succeeds, stream either has or will be freed automatically */
|
||||||
/* The leak here prevents a segfault */
|
if (php_stream_cast(stream, PHP_STREAM_AS_STDIO|PHP_STREAM_CAST_TRY_HARD|PHP_STREAM_CAST_RELEASE,
|
||||||
/* ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream()); */
|
(void**)&retval, REPORT_ERRORS) == FAILURE)
|
||||||
}
|
{
|
||||||
else {
|
|
||||||
php_stream_close(stream);
|
php_stream_close(stream);
|
||||||
if (opened_path && *opened_path)
|
if (opened_path && *opened_path)
|
||||||
efree(*opened_path);
|
efree(*opened_path);
|
||||||
|
|
|
@ -675,10 +675,11 @@ static size_t php_sockop_read(php_stream *stream, char *buf, size_t count)
|
||||||
return ret;
|
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;
|
php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
|
||||||
|
|
||||||
|
if (close_handle) {
|
||||||
#if HAVE_OPENSSL_EXT
|
#if HAVE_OPENSSL_EXT
|
||||||
if (sock->ssl_active) {
|
if (sock->ssl_active) {
|
||||||
SSL_shutdown(sock->ssl_handle);
|
SSL_shutdown(sock->ssl_handle);
|
||||||
|
@ -691,6 +692,7 @@ static int php_sockop_close(php_stream *stream)
|
||||||
shutdown(sock->socket, 0);
|
shutdown(sock->socket, 0);
|
||||||
closesocket(sock->socket);
|
closesocket(sock->socket);
|
||||||
|
|
||||||
|
}
|
||||||
if (sock->readbuf)
|
if (sock->readbuf)
|
||||||
pefree(sock->readbuf, php_stream_is_persistent(stream));
|
pefree(sock->readbuf, php_stream_is_persistent(stream));
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ typedef struct _php_stream_ops {
|
||||||
/* stdio like functions - these are mandatory! */
|
/* stdio like functions - these are mandatory! */
|
||||||
size_t (*write)(php_stream *stream, const char *buf, size_t count);
|
size_t (*write)(php_stream *stream, const char *buf, size_t count);
|
||||||
size_t (*read)(php_stream *stream, 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);
|
int (*flush)(php_stream *stream);
|
||||||
/* these are optional */
|
/* these are optional */
|
||||||
int (*seek)(php_stream *stream, off_t offset, int whence);
|
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) */
|
/* try really, really hard to make sure the cast happens (socketpair) */
|
||||||
#define PHP_STREAM_CAST_TRY_HARD 0x80000000
|
#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);
|
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 */
|
/* 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)
|
#define php_stream_can_cast(stream, as) php_stream_cast(stream, as, NULL, 0)
|
||||||
|
|
|
@ -69,6 +69,7 @@ PHPAPI int php_stream_free(php_stream *stream, int call_dtor) /* {{{ */
|
||||||
|
|
||||||
if (stream->wrapper && stream->wrapper->destroy) {
|
if (stream->wrapper && stream->wrapper->destroy) {
|
||||||
stream->wrapper->destroy(stream);
|
stream->wrapper->destroy(stream);
|
||||||
|
stream->wrapper = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (call_dtor) {
|
if (call_dtor) {
|
||||||
|
@ -84,9 +85,12 @@ PHPAPI int php_stream_free(php_stream *stream, int call_dtor) /* {{{ */
|
||||||
}
|
}
|
||||||
|
|
||||||
php_stream_flush(stream);
|
php_stream_flush(stream);
|
||||||
ret = stream->ops->close(stream);
|
}
|
||||||
|
|
||||||
|
ret = stream->ops->close(stream, call_dtor);
|
||||||
stream->abstract = NULL;
|
stream->abstract = NULL;
|
||||||
|
|
||||||
|
if (call_dtor) {
|
||||||
/* tidy up any FILE* that might have been fdopened */
|
/* tidy up any FILE* that might have been fdopened */
|
||||||
if (stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FDOPEN && stream->stdiocast) {
|
if (stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FDOPEN && stream->stdiocast) {
|
||||||
fclose(stream->stdiocast);
|
fclose(stream->stdiocast);
|
||||||
|
@ -96,6 +100,7 @@ PHPAPI int php_stream_free(php_stream *stream, int call_dtor) /* {{{ */
|
||||||
|
|
||||||
if (stream->wrapperdata) {
|
if (stream->wrapperdata) {
|
||||||
FREE_ZVAL(stream->wrapperdata);
|
FREE_ZVAL(stream->wrapperdata);
|
||||||
|
stream->wrapperdata = NULL;
|
||||||
}
|
}
|
||||||
pefree(stream, stream->is_persistent);
|
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);
|
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;
|
int ret;
|
||||||
php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
|
php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
|
||||||
|
|
||||||
assert(data != NULL);
|
assert(data != NULL);
|
||||||
|
|
||||||
|
if (close_handle) {
|
||||||
if (data->is_pipe) {
|
if (data->is_pipe) {
|
||||||
ret = pclose(data->file);
|
ret = pclose(data->file);
|
||||||
} else {
|
} else {
|
||||||
ret = fclose(data->file);
|
ret = fclose(data->file);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
efree(data);
|
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) /* {{{ */
|
PHPAPI int php_stream_cast(php_stream *stream, int castas, void **ret, int show_err) /* {{{ */
|
||||||
{
|
{
|
||||||
|
int flags = castas & PHP_STREAM_CAST_MASK;
|
||||||
/* trying hard is not yet implemented */
|
castas &= ~PHP_STREAM_CAST_MASK;
|
||||||
castas &= ~PHP_STREAM_CAST_TRY_HARD;
|
|
||||||
|
|
||||||
if (castas == PHP_STREAM_AS_STDIO) {
|
if (castas == PHP_STREAM_AS_STDIO) {
|
||||||
if (stream->stdiocast) {
|
if (stream->stdiocast) {
|
||||||
if (ret) {
|
if (ret) {
|
||||||
*ret = stream->stdiocast;
|
*ret = stream->stdiocast;
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
goto exit_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->ops->cast && stream->ops->cast(stream, castas, ret) == SUCCESS)
|
if (stream->ops->cast && stream->ops->cast(stream, castas, ret) == SUCCESS)
|
||||||
|
@ -783,7 +791,7 @@ PHPAPI int php_stream_cast(php_stream *stream, int castas, void **ret, int show_
|
||||||
*ret = fopencookie(stream, stream->mode, stream_cookie_functions);
|
*ret = fopencookie(stream, stream->mode, stream_cookie_functions);
|
||||||
|
|
||||||
if (*ret != NULL) {
|
if (*ret != NULL) {
|
||||||
stream->fclose_stdiocast = 1;
|
stream->fclose_stdiocast = PHP_STREAM_FCLOSE_FOPENCOOKIE;
|
||||||
goto exit_success;
|
goto exit_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -827,6 +835,19 @@ exit_success:
|
||||||
if (castas == PHP_STREAM_AS_STDIO && ret)
|
if (castas == PHP_STREAM_AS_STDIO && ret)
|
||||||
stream->stdiocast = *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;
|
return SUCCESS;
|
||||||
|
|
||||||
} /* }}} */
|
} /* }}} */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue