Assorted ssh2 patches
| From: | Mike Sullivan | Date: | Tue, 02 Dec 2008 14:17:58 +0000 |
| Subject: | Assorted ssh2 patches | ||
| Groups: | php.pecl.dev | ||
| Request: | Send a blank email to pecl-dev+get-5940@lists.php.net to get a copy of this message | ||
Hi,
I'm attaching patches for assorted bugs in the ssh2 extension. I'm
interested in contributing more fixes if these are ok. I've been working
with Scott while creating these patches; he recommended I attach them here.
The files are named in an order, but I don't think there's any explicit
dependency between them. (Hopefully they are attached in order, but they
probably won't be...)
Patches:
---
* 01-ssh2-bug14397: fix for PHP 5.3 compilation
(http://pecl.php.net/bugs/bug.php?id=14397)
* 02-cvsignore: missing .cvsignore file (just ignores the build-related
files)
* 03-ssh2-bug12008: segfault when using a non-blocking ssh2 channel stream
(http://pecl.php.net/bugs/bug.php?id=12008)
* 04-segfault-invalid-path: segfault when you pass an invalid path into the
ssh2 stream handler
* 05-ssh2-bug13439: inverted return value for sftp streams from
unlink/rename/mkdir/rmdir. Additionally, there are some memory leak fixes
here that affect the context directly next to the return values.
(http://pecl.php.net/bugs/bug.php?id=13439)
* 06-memleak-sftp-urlstat: memory leak in the urlstat function for sftp
streams
* 07-memleak-sftp-rename: memory leak with sftp streams when renaming
---
If you have any questions, let me know. Thanks!
Mike Sullivan
Index: ssh2_fopen_wrappers.c =================================================================== --- ssh2_fopen_wrappers.c (revision 5) +++ ssh2_fopen_wrappers.c (revision 6) @@ -128,6 +128,9 @@ int username_len = 0, password_len = 0; resource = php_url_parse(path); + if (!resource) { + return NULL; + } if (strncmp(resource->scheme, "ssh2.", sizeof("ssh2.") - 1)) { /* Not an ssh wrapper */ Index: ssh2_sftp.c =================================================================== --- ssh2_sftp.c (revision 6) +++ ssh2_sftp.c (revision 7) @@ -417,7 +417,10 @@ resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC); if (!resource || !session || !sftp || !resource->path) { - return -1; + if (resource) { + php_url_free(resource); + } + return 0; } result = libssh2_sftp_unlink(sftp, resource->path); @@ -425,7 +428,8 @@ zend_list_delete(sftp_rsrcid); - return (result == 0) ? 0 : -1; + /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */ + return (result == 0) ? -1 : 0; } /* }}} */ @@ -441,18 +445,24 @@ if (strncmp(url_from, "ssh2.sftp://", sizeof("ssh2.sftp://") - 1) || strncmp(url_to, "ssh2.sftp://", sizeof("ssh2.sftp://") - 1)) { - return -1; + return 0; } resource_to = php_url_parse(url_to); if (!resource_to || !resource_to->path) { - return -1; + if (resource_to) { + php_url_free(resource_to); + } + return 0; } resource = php_ssh2_fopen_wraper_parse_path(url_from, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC); if (!resource || !session || !sftp || !resource->path) { + if (resource) { + php_url_free(resource); + } php_url_free(resource_to); - return -1; + return 0; } result = libssh2_sftp_rename(sftp, resource->path, resource_to->path); @@ -460,7 +470,8 @@ zend_list_delete(sftp_rsrcid); - return (result == 0) ? 0 : -1; + /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */ + return (result == 0) ? -1 : 0; } /* }}} */ @@ -476,7 +487,10 @@ resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC); if (!resource || !session || !sftp || !resource->path) { - return -1; + if (resource) { + php_url_free(resource); + } + return 0; } if (options & PHP_STREAM_MKDIR_RECURSIVE) { @@ -492,7 +506,8 @@ zend_list_delete(sftp_rsrcid); - return (result == 0) ? 0 : -1; + /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */ + return (result == 0) ? -1 : 0; } /* }}} */ @@ -508,7 +523,10 @@ resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC); if (!resource || !session || !sftp || !resource->path) { - return -1; + if (resource) { + php_url_free(resource); + } + return 0; } result = libssh2_sftp_rmdir(sftp, resource->path); @@ -516,7 +534,8 @@ zend_list_delete(sftp_rsrcid); - return (result == 0) ? 0 : -1; + /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */ + return (result == 0) ? -1 : 0; } /* }}} */ #endif Index: ssh2_sftp.c =================================================================== --- ssh2_sftp.c (revision 7) +++ ssh2_sftp.c (revision 8) @@ -397,6 +397,8 @@ zend_list_delete(sftp_rsrcid); return -1; } + + php_url_free(resource); /* parse_path addrefs the resource, but we're not holding on to it so we have to delref it before we leave */ zend_list_delete(sftp_rsrcid); Index: ssh2_sftp.c =================================================================== --- ssh2_sftp.c (revision 8) +++ ssh2_sftp.c (revision 9) @@ -469,6 +469,7 @@ result = libssh2_sftp_rename(sftp, resource->path, resource_to->path); php_url_free(resource); + php_url_free(resource_to); zend_list_delete(sftp_rsrcid); Index: ssh2.c =================================================================== --- ssh2.c (revision 1) +++ ssh2.c (revision 2) @@ -889,7 +889,7 @@ for(i = 0; i < numfds; i++) { zval *subarray = *pollmap[i]; - if (!subarray->is_ref && subarray->refcount > 1) { + if (!Z_ISREF_P(subarray) && Z_REFCOUNT_P(subarray) > 1) { /* Make a new copy of the subarray zval* */ MAKE_STD_ZVAL(subarray); *subarray = **pollmap[i]; @@ -899,8 +899,8 @@ zval_copy_ctor(subarray); /* Fixup its refcount */ - subarray->is_ref = 0; - subarray->refcount = 1; + Z_UNSET_ISREF_P(subarray); + Z_SET_REFCOUNT_P(subarray, 1); } zend_hash_del(Z_ARRVAL_P(subarray), "revents", sizeof("revents")); add_assoc_long(subarray, "revents", pollfds[i].revents); @@ -1009,8 +1009,8 @@ } zval_copy_ctor(©val); - copyval.is_ref = 0; - copyval.refcount = 1; + Z_UNSET_ISREF_P(©val); + Z_SET_REFCOUNT_P(©val, 1); convert_to_string(©val); if (*key == '*') { Index: php_ssh2.h =================================================================== --- php_ssh2.h (revision 1) +++ php_ssh2.h (revision 2) @@ -109,7 +109,33 @@ #define SSH2_TSRMLS_FETCH(datap) #endif +/* < 5.3 compatibility */ +#ifndef Z_REFCOUNT_P +#define Z_REFCOUNT_P(pz) (pz)->refcount +#define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz)) +#endif +#ifndef Z_SET_REFCOUNT_P +#define Z_SET_REFCOUNT_P(pz, rc) (pz)->refcount = rc +#define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc) +#endif + +#ifndef Z_ISREF_P +#define Z_ISREF_P(pz) (pz)->is_ref +#define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz)) +#endif + +#ifndef Z_SET_ISREF_P +#define Z_SET_ISREF_P(pz) (pz)->is_ref = 1 +#define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz)) +#endif + +#ifndef Z_UNSET_ISREF_P +#define Z_UNSET_ISREF_P(pz) (pz)->is_ref = 0 +#define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz)) +#endif + + typedef struct _php_ssh2_channel_data { LIBSSH2_CHANNEL *channel; Index: .cvsignore =================================================================== --- .cvsignore (revision 0) +++ .cvsignore (revision 4) @@ -0,0 +1,28 @@ +.deps +.libs +Makefile +Makefile.fragments +Makefile.global +Makefile.objects +acinclude.m4 +aclocal.m4 +autom4te.cache +build +config.guess +config.h +config.h.in +config.log +config.nice +config.status +config.sub +configure +configure.in +include +install-sh +libtool +ltmain.sh +missing +mkinstalldirs +modules +*.la +*.lo Index: ssh2_fopen_wrappers.c =================================================================== --- ssh2_fopen_wrappers.c (revision 4) +++ ssh2_fopen_wrappers.c (revision 5) @@ -40,10 +40,13 @@ static size_t php_ssh2_channel_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) { php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract; + ssize_t readstate; stream->eof = libssh2_channel_eof(abstract->channel); libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking); - return libssh2_channel_read_ex(abstract->channel, abstract->streamid, buf, count); + + readstate = libssh2_channel_read_ex(abstract->channel, abstract->streamid, buf, count); + return (readstate == LIBSSH2_ERROR_EAGAIN ? 0 : readstate); } static int php_ssh2_channel_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
Index: ssh2_fopen_wrappers.c =================================================================== --- ssh2_fopen_wrappers.c (revision 5) +++ ssh2_fopen_wrappers.c (revision 6) @@ -128,6 +128,9 @@ int username_len = 0, password_len = 0; resource = php_url_parse(path); + if (!resource) { + return NULL; + } if (strncmp(resource->scheme, "ssh2.", sizeof("ssh2.") - 1)) { /* Not an ssh wrapper */ Index: ssh2_sftp.c =================================================================== --- ssh2_sftp.c (revision 6) +++ ssh2_sftp.c (revision 7) @@ -417,7 +417,10 @@ resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC); if (!resource || !session || !sftp || !resource->path) { - return -1; + if (resource) { + php_url_free(resource); + } + return 0; } result = libssh2_sftp_unlink(sftp, resource->path); @@ -425,7 +428,8 @@ zend_list_delete(sftp_rsrcid); - return (result == 0) ? 0 : -1; + /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */ + return (result == 0) ? -1 : 0; } /* }}} */ @@ -441,18 +445,24 @@ if (strncmp(url_from, "ssh2.sftp://", sizeof("ssh2.sftp://") - 1) || strncmp(url_to, "ssh2.sftp://", sizeof("ssh2.sftp://") - 1)) { - return -1; + return 0; } resource_to = php_url_parse(url_to); if (!resource_to || !resource_to->path) { - return -1; + if (resource_to) { + php_url_free(resource_to); + } + return 0; } resource = php_ssh2_fopen_wraper_parse_path(url_from, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC); if (!resource || !session || !sftp || !resource->path) { + if (resource) { + php_url_free(resource); + } php_url_free(resource_to); - return -1; + return 0; } result = libssh2_sftp_rename(sftp, resource->path, resource_to->path); @@ -460,7 +470,8 @@ zend_list_delete(sftp_rsrcid); - return (result == 0) ? 0 : -1; + /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */ + return (result == 0) ? -1 : 0; } /* }}} */ @@ -476,7 +487,10 @@ resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC); if (!resource || !session || !sftp || !resource->path) { - return -1; + if (resource) { + php_url_free(resource); + } + return 0; } if (options & PHP_STREAM_MKDIR_RECURSIVE) { @@ -492,7 +506,8 @@ zend_list_delete(sftp_rsrcid); - return (result == 0) ? 0 : -1; + /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */ + return (result == 0) ? -1 : 0; } /* }}} */ @@ -508,7 +523,10 @@ resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC); if (!resource || !session || !sftp || !resource->path) { - return -1; + if (resource) { + php_url_free(resource); + } + return 0; } result = libssh2_sftp_rmdir(sftp, resource->path); @@ -516,7 +534,8 @@ zend_list_delete(sftp_rsrcid); - return (result == 0) ? 0 : -1; + /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */ + return (result == 0) ? -1 : 0; } /* }}} */ #endif Index: ssh2_sftp.c =================================================================== --- ssh2_sftp.c (revision 7) +++ ssh2_sftp.c (revision 8) @@ -397,6 +397,8 @@ zend_list_delete(sftp_rsrcid); return -1; } + + php_url_free(resource); /* parse_path addrefs the resource, but we're not holding on to it so we have to delref it before we leave */ zend_list_delete(sftp_rsrcid); Index: ssh2_sftp.c =================================================================== --- ssh2_sftp.c (revision 8) +++ ssh2_sftp.c (revision 9) @@ -469,6 +469,7 @@ result = libssh2_sftp_rename(sftp, resource->path, resource_to->path); php_url_free(resource); + php_url_free(resource_to); zend_list_delete(sftp_rsrcid); Index: ssh2.c =================================================================== --- ssh2.c (revision 1) +++ ssh2.c (revision 2) @@ -889,7 +889,7 @@ for(i = 0; i < numfds; i++) { zval *subarray = *pollmap[i]; - if (!subarray->is_ref && subarray->refcount > 1) { + if (!Z_ISREF_P(subarray) && Z_REFCOUNT_P(subarray) > 1) { /* Make a new copy of the subarray zval* */ MAKE_STD_ZVAL(subarray); *subarray = **pollmap[i]; @@ -899,8 +899,8 @@ zval_copy_ctor(subarray); /* Fixup its refcount */ - subarray->is_ref = 0; - subarray->refcount = 1; + Z_UNSET_ISREF_P(subarray); + Z_SET_REFCOUNT_P(subarray, 1); } zend_hash_del(Z_ARRVAL_P(subarray), "revents", sizeof("revents")); add_assoc_long(subarray, "revents", pollfds[i].revents); @@ -1009,8 +1009,8 @@ } zval_copy_ctor(©val); - copyval.is_ref = 0; - copyval.refcount = 1; + Z_UNSET_ISREF_P(©val); + Z_SET_REFCOUNT_P(©val, 1); convert_to_string(©val); if (*key == '*') { Index: php_ssh2.h =================================================================== --- php_ssh2.h (revision 1) +++ php_ssh2.h (revision 2) @@ -109,7 +109,33 @@ #define SSH2_TSRMLS_FETCH(datap) #endif +/* < 5.3 compatibility */ +#ifndef Z_REFCOUNT_P +#define Z_REFCOUNT_P(pz) (pz)->refcount +#define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz)) +#endif +#ifndef Z_SET_REFCOUNT_P +#define Z_SET_REFCOUNT_P(pz, rc) (pz)->refcount = rc +#define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc) +#endif + +#ifndef Z_ISREF_P +#define Z_ISREF_P(pz) (pz)->is_ref +#define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz)) +#endif + +#ifndef Z_SET_ISREF_P +#define Z_SET_ISREF_P(pz) (pz)->is_ref = 1 +#define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz)) +#endif + +#ifndef Z_UNSET_ISREF_P +#define Z_UNSET_ISREF_P(pz) (pz)->is_ref = 0 +#define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz)) +#endif + + typedef struct _php_ssh2_channel_data { LIBSSH2_CHANNEL *channel; Index: .cvsignore =================================================================== --- .cvsignore (revision 0) +++ .cvsignore (revision 4) @@ -0,0 +1,28 @@ +.deps +.libs +Makefile +Makefile.fragments +Makefile.global +Makefile.objects +acinclude.m4 +aclocal.m4 +autom4te.cache +build +config.guess +config.h +config.h.in +config.log +config.nice +config.status +config.sub +configure +configure.in +include +install-sh +libtool +ltmain.sh +missing +mkinstalldirs +modules +*.la +*.lo Index: ssh2_fopen_wrappers.c =================================================================== --- ssh2_fopen_wrappers.c (revision 4) +++ ssh2_fopen_wrappers.c (revision 5) @@ -40,10 +40,13 @@ static size_t php_ssh2_channel_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) { php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract; + ssize_t readstate; stream->eof = libssh2_channel_eof(abstract->channel); libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking); - return libssh2_channel_read_ex(abstract->channel, abstract->streamid, buf, count); + + readstate = libssh2_channel_read_ex(abstract->channel, abstract->streamid, buf, count); + return (readstate == LIBSSH2_ERROR_EAGAIN ? 0 : readstate); } static int php_ssh2_channel_stream_close(php_stream *stream, int close_handle TSRMLS_DC)