From 3af04f49f4705e57097a9a17df416e324c2a587e Mon Sep 17 00:00:00 2001 From: Mark Karpeles Date: Thu, 25 Jun 2015 18:24:58 +0900 Subject: [PATCH 1/2] transport register: allocate memory for callback to avoid segfault when newly registered transport is actually called --- helper.c | 37 +++++++++++++++++++++++++++++++++++++ helper.h | 4 +++- php_git2.h | 1 + transport.c | 2 +- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/helper.c b/helper.c index 84c898d2f1..76b3bcd85c 100644 --- a/helper.c +++ b/helper.c @@ -217,6 +217,35 @@ int php_git2_cb_init(php_git2_cb_t **out, zend_fcall_info *fci, zend_fcall_info_ cb->payload = payload; cb->fci = fci; cb->fcc = fcc; + cb->is_copy = 0; + GIT2_TSRMLS_SET2(cb, TSRMLS_C); + + *out = cb; + return 0; +} + +int php_git2_cb_init_copy(php_git2_cb_t **out, zend_fcall_info *fci, zend_fcall_info_cache *fcc, void *payload TSRMLS_DC) +{ + php_git2_cb_t *cb; + + cb = (struct php_git2_cb_t*)emalloc(sizeof(php_git2_cb_t)); + if (cb == NULL) { + return 1; + } + + cb->payload = payload; + // use fci->size instead of sizeof? + cb->fci = (zend_fcall_info*)emalloc(sizeof(zend_fcall_info)); + cb->fcc = (zend_fcall_info_cache*)emalloc(sizeof(zend_fcall_info_cache)); + memcpy(cb->fci, fci, sizeof(zend_fcall_info)); + memcpy(cb->fcc, fcc, sizeof(zend_fcall_info_cache)); + Z_ADDREF_P(cb->fci->function_name); +#if PHP_VERSION_ID >= 50300 + if (cb->fci->object_ptr) { + Z_ADDREF_P(cb->fci->object_ptr); + } +#endif + cb->is_copy = 1; GIT2_TSRMLS_SET2(cb, TSRMLS_C); *out = cb; @@ -225,6 +254,14 @@ int php_git2_cb_init(php_git2_cb_t **out, zend_fcall_info *fci, zend_fcall_info_ void php_git2_cb_free(php_git2_cb_t *target) { + if (target->is_copy) { + Z_DELREF_P(target->fci->function_name); +#if PHP_VERSION_ID >= 50300 + if (target->fci->object_ptr) { + Z_DELREF_P(target->fci->object_ptr); + } +#endif + } efree(target); } diff --git a/helper.h b/helper.h index 424f1c3f89..3cf5e942d5 100644 --- a/helper.h +++ b/helper.h @@ -49,6 +49,8 @@ int php_git2_call_function_v( int php_git2_cb_init(php_git2_cb_t **out, zend_fcall_info *fci, zend_fcall_info_cache *fcc, void *payload TSRMLS_DC); +int php_git2_cb_init_copy(php_git2_cb_t **out, zend_fcall_info *fci, zend_fcall_info_cache *fcc, void *payload TSRMLS_DC); + void php_git2_cb_free(php_git2_cb_t *target); void php_git2_array_to_strarray(git_strarray *out, zval *array TSRMLS_DC); @@ -100,4 +102,4 @@ void php_git2_fcall_info_wrapper(zval *target, zend_fcall_info **out_fci, zend_f void php_git2_fcall_info_wrapper2(zval *target, zend_fcall_info *fci, zend_fcall_info_cache *fcc TSRMLS_DC); -#endif \ No newline at end of file +#endif diff --git a/php_git2.h b/php_git2.h index 4c5493a976..43b9c2850b 100644 --- a/php_git2.h +++ b/php_git2.h @@ -203,6 +203,7 @@ typedef struct php_git2_cb_t { zval *payload; zend_fcall_info *fci; zend_fcall_info_cache *fcc; + int is_copy; GIT2_TSRMLS_DECL } php_git2_cb_t; diff --git a/transport.c b/transport.c index 4904517ab5..17356225f0 100644 --- a/transport.c +++ b/transport.c @@ -73,7 +73,7 @@ PHP_FUNCTION(git_transport_register) return; } - if (php_git2_cb_init(&cb, &fci, &fcc, param TSRMLS_CC)) { + if (php_git2_cb_init_copy(&cb, &fci, &fcc, param TSRMLS_CC)) { RETURN_FALSE; } result = git_transport_register(prefix, priority, php_git2_transport_cb, cb); From f14f1670b99e07aa98cd31d7d9ed4a5391e1aaab Mon Sep 17 00:00:00 2001 From: Mark Karpeles Date: Thu, 25 Jun 2015 18:29:13 +0900 Subject: [PATCH 2/2] do not free callback as we are to use it again --- transport.c | 1 - 1 file changed, 1 deletion(-) diff --git a/transport.c b/transport.c index 17356225f0..4860723f60 100644 --- a/transport.c +++ b/transport.c @@ -77,7 +77,6 @@ PHP_FUNCTION(git_transport_register) RETURN_FALSE; } result = git_transport_register(prefix, priority, php_git2_transport_cb, cb); - php_git2_cb_free(cb); RETURN_LONG(result); } /* }}} */