mirror of
https://github.com/php/php-src.git
synced 2025-08-20 01:14:28 +02:00
fix memleak in unlink()
This commit is contained in:
parent
74d7701b2b
commit
78f1b9401b
3 changed files with 42 additions and 12 deletions
|
@ -246,7 +246,7 @@ phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int pa
|
||||||
* Retrieve a copy of the file information on a single file within a phar, or null.
|
* Retrieve a copy of the file information on a single file within a phar, or null.
|
||||||
* This also transfers the open file pointer, if any, to the entry.
|
* This also transfers the open file pointer, if any, to the entry.
|
||||||
*/
|
*/
|
||||||
static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode TSRMLS_DC) /* {{{ */
|
static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
phar_archive_data *phar;
|
phar_archive_data *phar;
|
||||||
phar_entry_info *entry;
|
phar_entry_info *entry;
|
||||||
|
@ -259,18 +259,26 @@ static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
*ret = NULL;
|
*ret = NULL;
|
||||||
|
*error = (char *) emalloc(200 + fname_len);
|
||||||
|
**error = '\0';
|
||||||
if (for_write && PHAR_G(readonly)) {
|
if (for_write && PHAR_G(readonly)) {
|
||||||
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "phar error: file \"%s\" cannot opened for writing, disabled by ini setting", fname);
|
if (error) {
|
||||||
|
sprintf(*error, "phar error: file \"%s\" cannot opened for writing, disabled by ini setting", fname);
|
||||||
|
}
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
if ((phar = phar_get_archive(fname, fname_len, NULL, 0 TSRMLS_CC)) != NULL) {
|
if ((phar = phar_get_archive(fname, fname_len, NULL, 0 TSRMLS_CC)) != NULL) {
|
||||||
if ((entry = phar_get_entry_info(phar, path, path_len TSRMLS_CC)) != NULL) {
|
if ((entry = phar_get_entry_info(phar, path, path_len TSRMLS_CC)) != NULL) {
|
||||||
if (entry->is_modified && !for_write) {
|
if (entry->is_modified && !for_write) {
|
||||||
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "phar error: file \"%s\" cannot opened for reading, writable file pointers are open", fname);
|
if (error) {
|
||||||
|
sprintf(*error, "phar error: file \"%s\" cannot opened for reading, writable file pointers are open", fname);
|
||||||
|
}
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
if (entry->fp_refcount && for_write) {
|
if (entry->fp_refcount && for_write) {
|
||||||
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "phar error: file \"%s\" cannot opened for writing, readable file pointers are open", fname);
|
if (error) {
|
||||||
|
sprintf(*error, "phar error: file \"%s\" cannot opened for writing, readable file pointers are open", fname);
|
||||||
|
}
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
if (entry->is_deleted) {
|
if (entry->is_deleted) {
|
||||||
|
@ -363,7 +371,7 @@ void phar_entry_remove(phar_entry_data *idata TSRMLS_DC) /* {{{ */
|
||||||
/**
|
/**
|
||||||
* Create a new dummy file slot within a writeable phar for a newly created file
|
* Create a new dummy file slot within a writeable phar for a newly created file
|
||||||
*/
|
*/
|
||||||
phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode TSRMLS_DC) /* {{{ */
|
phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
phar_archive_data *phar;
|
phar_archive_data *phar;
|
||||||
phar_entry_info *entry, etemp;
|
phar_entry_info *entry, etemp;
|
||||||
|
@ -373,7 +381,7 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, path_len, mode TSRMLS_CC)) {
|
if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, path_len, mode, error TSRMLS_CC)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -1260,6 +1268,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
|
||||||
phar_entry_data *idata;
|
phar_entry_data *idata;
|
||||||
char *internal_file;
|
char *internal_file;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
char *error;
|
||||||
char *filter_name;
|
char *filter_name;
|
||||||
char tmpbuf[8];
|
char tmpbuf[8];
|
||||||
php_url *resource = NULL;
|
php_url *resource = NULL;
|
||||||
|
@ -1290,12 +1299,17 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
|
||||||
/* strip leading "/" */
|
/* strip leading "/" */
|
||||||
internal_file = estrdup(resource->path + 1);
|
internal_file = estrdup(resource->path + 1);
|
||||||
if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) {
|
if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) {
|
||||||
if (NULL == (idata = phar_get_or_create_entry_data(resource->host, strlen(resource->host), internal_file, strlen(internal_file), mode TSRMLS_CC))) {
|
if (NULL == (idata = phar_get_or_create_entry_data(resource->host, strlen(resource->host), internal_file, strlen(internal_file), mode, &error TSRMLS_CC))) {
|
||||||
|
if (error[0]) {
|
||||||
|
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
|
||||||
|
}
|
||||||
|
efree(error);
|
||||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: file \"%s\" could not be created in phar \"%s\"", internal_file, resource->host);
|
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: file \"%s\" could not be created in phar \"%s\"", internal_file, resource->host);
|
||||||
efree(internal_file);
|
efree(internal_file);
|
||||||
php_url_free(resource);
|
php_url_free(resource);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
efree(error);
|
||||||
fpf = php_stream_alloc(&phar_ops, idata, NULL, mode);
|
fpf = php_stream_alloc(&phar_ops, idata, NULL, mode);
|
||||||
php_url_free(resource);
|
php_url_free(resource);
|
||||||
efree(internal_file);
|
efree(internal_file);
|
||||||
|
@ -1312,12 +1326,18 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
|
||||||
}
|
}
|
||||||
return fpf;
|
return fpf;
|
||||||
} else {
|
} else {
|
||||||
if ((FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r" TSRMLS_CC)) || !idata) {
|
if ((FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r", &error TSRMLS_CC)) || !idata) {
|
||||||
|
if (error[0]) {
|
||||||
|
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
|
||||||
|
}
|
||||||
|
efree(error);
|
||||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: \"%s\" is not a file in phar \"%s\"", internal_file, resource->host);
|
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: \"%s\" is not a file in phar \"%s\"", internal_file, resource->host);
|
||||||
efree(internal_file);
|
efree(internal_file);
|
||||||
php_url_free(resource);
|
php_url_free(resource);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* alloced in get_entry_data */
|
||||||
|
efree(error);
|
||||||
}
|
}
|
||||||
php_url_free(resource);
|
php_url_free(resource);
|
||||||
|
|
||||||
|
@ -2416,6 +2436,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
|
||||||
{
|
{
|
||||||
php_url *resource;
|
php_url *resource;
|
||||||
char *internal_file;
|
char *internal_file;
|
||||||
|
char *error;
|
||||||
phar_entry_data *idata;
|
phar_entry_data *idata;
|
||||||
|
|
||||||
resource = php_url_parse(url);
|
resource = php_url_parse(url);
|
||||||
|
@ -2445,12 +2466,17 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
|
||||||
|
|
||||||
/* need to copy to strip leading "/", will get touched again */
|
/* need to copy to strip leading "/", will get touched again */
|
||||||
internal_file = estrdup(resource->path + 1);
|
internal_file = estrdup(resource->path + 1);
|
||||||
if (FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r" TSRMLS_CC)) {
|
if (FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r", &error TSRMLS_CC)) {
|
||||||
/* constraints of fp refcount were not met */
|
/* constraints of fp refcount were not met */
|
||||||
|
if (error[0]) {
|
||||||
|
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
|
||||||
|
}
|
||||||
|
efree(error);
|
||||||
efree(internal_file);
|
efree(internal_file);
|
||||||
php_url_free(resource);
|
php_url_free(resource);
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
efree(error);
|
||||||
if (!idata) {
|
if (!idata) {
|
||||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: \"%s\" is not a file in phar \"%s\", cannot unlink", internal_file, resource->host);
|
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: \"%s\" is not a file in phar \"%s\", cannot unlink", internal_file, resource->host);
|
||||||
efree(internal_file);
|
efree(internal_file);
|
||||||
|
@ -2467,6 +2493,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
|
||||||
phar_entry_delref(idata TSRMLS_CC);
|
phar_entry_delref(idata TSRMLS_CC);
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
php_url_free(resource);
|
||||||
efree(internal_file);
|
efree(internal_file);
|
||||||
phar_entry_remove(idata TSRMLS_CC);
|
phar_entry_remove(idata TSRMLS_CC);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|
|
@ -249,7 +249,7 @@ int phar_entry_delref(phar_entry_data *idata TSRMLS_DC);
|
||||||
|
|
||||||
void phar_destroy_phar_data(phar_archive_data *data TSRMLS_DC);
|
void phar_destroy_phar_data(phar_archive_data *data TSRMLS_DC);
|
||||||
phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len TSRMLS_DC);
|
phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len TSRMLS_DC);
|
||||||
phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode TSRMLS_DC);
|
phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC);
|
||||||
int phar_flush(phar_archive_data *archive, char *user_stub, long len TSRMLS_DC);
|
int phar_flush(phar_archive_data *archive, char *user_stub, long len TSRMLS_DC);
|
||||||
int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC);
|
int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC);
|
||||||
|
|
||||||
|
|
|
@ -343,6 +343,7 @@ PHP_METHOD(Phar, offsetGet)
|
||||||
PHP_METHOD(Phar, offsetSet)
|
PHP_METHOD(Phar, offsetSet)
|
||||||
{
|
{
|
||||||
char *fname;
|
char *fname;
|
||||||
|
char *error;
|
||||||
int fname_len;
|
int fname_len;
|
||||||
zval *contents;
|
zval *contents;
|
||||||
long contents_len = PHP_STREAM_COPY_ALL;
|
long contents_len = PHP_STREAM_COPY_ALL;
|
||||||
|
@ -363,9 +364,11 @@ PHP_METHOD(Phar, offsetSet)
|
||||||
if (Z_TYPE_P(contents) != IS_STRING && Z_TYPE_P(contents) != IS_RESOURCE) {
|
if (Z_TYPE_P(contents) != IS_STRING && Z_TYPE_P(contents) != IS_RESOURCE) {
|
||||||
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", fname);
|
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", fname);
|
||||||
}
|
}
|
||||||
if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, fname, fname_len, "w+b" TSRMLS_CC))) {
|
if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, fname, fname_len, "w+b", &error TSRMLS_CC))) {
|
||||||
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be created", fname);
|
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be created: %s", fname, error);
|
||||||
|
efree(error);
|
||||||
} else {
|
} else {
|
||||||
|
efree(error);
|
||||||
if (Z_TYPE_P(contents) == IS_STRING) {
|
if (Z_TYPE_P(contents) == IS_STRING) {
|
||||||
contents_len = php_stream_write(data->fp, Z_STRVAL_P(contents), Z_STRLEN_P(contents));
|
contents_len = php_stream_write(data->fp, Z_STRVAL_P(contents), Z_STRLEN_P(contents));
|
||||||
if (contents_len != Z_STRLEN_P(contents)) {
|
if (contents_len != Z_STRLEN_P(contents)) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue