[PECL-CVS] [pecl-networking-gearman] master: Merge pull request #48 from php/memory-audit

[email protected] (Rasmus Lerdorf via GitHub) Wed, 11 Mar 2026 02:59:50 +0000
Newsgroups php.pecl.cvs
Message-ID <[email protected]>
Author: Rasmus Lerdorf (rlerdorf)
Committer: GitHub (web-flow)
Pusher: rlerdorf
Date: 2026-03-11T02:59:48Z

Commit: https://github.com/php/pecl-networking-gearman/commit/b47100ad095ce53fdf1c6c3e194bf067b556d909
Raw diff: https://github.com/php/pecl-networking-gearman/commit/b47100ad095ce53fdf1c6c3e194bf067b556d909.diff

Merge pull request #48 from php/memory-audit

Fix several memory access issues

Changed paths:
  M  php_gearman.c
  M  php_gearman_client.c
  M  php_gearman_job.c
  M  php_gearman_task.c
  M  php_gearman_worker.c
  M  php_gearman_worker.h


Diff:

diff --git a/php_gearman.c b/php_gearman.c
index fc8bf74..474039e 100644
--- a/php_gearman.c
+++ b/php_gearman.c
@@ -112,6 +112,7 @@ PHP_MINIT_FUNCTION(gearman) {
 	gearman_worker_ce->create_object = gearman_worker_obj_new;
 	memcpy(&gearman_worker_obj_handlers, zend_get_std_object_handlers(), sizeof(gearman_worker_obj_handlers));
 	gearman_worker_obj_handlers.offset = XtOffsetOf(gearman_worker_obj, std);
+	gearman_worker_obj_handlers.free_obj = gearman_worker_free_obj;
 
 	INIT_CLASS_ENTRY(ce, "GearmanJob", class_GearmanJob_methods);
 	gearman_job_ce = zend_register_internal_class(&ce);
diff --git a/php_gearman_client.c b/php_gearman_client.c
index 38290a9..f2ae566 100644
--- a/php_gearman_client.c
+++ b/php_gearman_client.c
@@ -83,7 +83,9 @@ PHP_METHOD(GearmanClient, __destruct)
 
         if (intern->flags & GEARMAN_CLIENT_OBJ_CREATED) {
                 context = gearman_client_context(&(intern->client));
-                efree(context);
+                if (context) {
+                        efree(context);
+                }
 
                 gearman_client_free(&intern->client);
                 intern->flags &= ~GEARMAN_CLIENT_OBJ_CREATED;
@@ -416,7 +418,7 @@ static void gearman_client_do_work_handler(void* (*do_work_func)(
                 RETURN_EMPTY_STRING();
         }
 
-        ZVAL_STRINGL(return_value, (char *)result, (long)result_size);
+        ZVAL_STRINGL(return_value, (char *)result, result_size);
         efree(result);
 }
 /* }}} */
@@ -492,11 +494,6 @@ static void gearman_client_do_background_work_handler(gearman_return_t (*do_back
                 RETURN_EMPTY_STRING();
         }
 
-        if (! job_handle) {
-                zend_string_release(job_handle);
-                RETURN_EMPTY_STRING();
-        }
-
         RETURN_STR(job_handle);
 }
 /* }}} */
@@ -1251,7 +1248,9 @@ PHP_FUNCTION(gearman_client_set_context) {
         obj = Z_GEARMAN_CLIENT_P(zobj);
 
         old_context = gearman_client_context(&(obj->client));
-        efree(old_context);
+        if (old_context) {
+                efree(old_context);
+        }
 
         gearman_client_set_context(&(obj->client), (void*) estrndup(data, data_len));
         RETURN_TRUE;
diff --git a/php_gearman_job.c b/php_gearman_job.c
index c840f1e..97036c9 100644
--- a/php_gearman_job.c
+++ b/php_gearman_job.c
@@ -316,7 +316,7 @@ PHP_FUNCTION(gearman_job_workload) {
 	workload = gearman_job_workload(obj->job);
 	workload_len = gearman_job_workload_size(obj->job);
 
-	RETURN_STRINGL((char *)workload, (long) workload_len);
+	RETURN_STRINGL((char *)workload, workload_len);
 }
 /* }}} */
 
diff --git a/php_gearman_task.c b/php_gearman_task.c
index 8e7ea72..c3a9590 100644
--- a/php_gearman_task.c
+++ b/php_gearman_task.c
@@ -293,7 +293,7 @@ PHP_FUNCTION(gearman_task_data) {
 		data = gearman_task_data(obj->task);
 		data_len = gearman_task_data_size(obj->task);
 
-		RETURN_STRINGL((char *)data, (long) data_len);
+		RETURN_STRINGL((char *)data, data_len);
 	}
 	RETURN_FALSE;
 }
@@ -378,12 +378,13 @@ PHP_FUNCTION(gearman_task_recv_data) {
 		!gearman_client_has_option(&Z_GEARMAN_CLIENT_P(&obj->zclient)->client, GEARMAN_CLIENT_UNBUFFERED_RESULT)) {
 		php_error_docref(NULL, E_WARNING,  "%s",
 						 gearman_client_error(&Z_GEARMAN_CLIENT_P(&obj->zclient)->client));
+		efree(data_buffer);
 		RETURN_FALSE;
 	}
 
 	array_init(return_value);
-	add_next_index_long(return_value, (long)data_len);
-	add_next_index_stringl(return_value, (char *)data_buffer,
-						  (long)data_len);
+	add_next_index_long(return_value, data_len);
+	add_next_index_stringl(return_value, (char *)data_buffer, data_len);
+	efree(data_buffer);
 }
 /* }}} */
diff --git a/php_gearman_worker.c b/php_gearman_worker.c
index c49e1e2..7695a2d 100644
--- a/php_gearman_worker.c
+++ b/php_gearman_worker.c
@@ -57,6 +57,19 @@ PHP_METHOD(GearmanWorker, __construct) {
 }
 /* }}} */
 
+void gearman_worker_free_obj(zend_object *object) {
+        gearman_worker_obj *intern = gearman_worker_fetch_object(object);
+
+        if (intern->flags & GEARMAN_WORKER_OBJ_CREATED) {
+                gearman_worker_free(&(intern->worker));
+                intern->flags &= ~GEARMAN_WORKER_OBJ_CREATED;
+        }
+
+        zval_dtor(&intern->cb_list);
+
+        zend_object_std_dtor(&intern->std);
+}
+
 /* {{{ proto object GearmanWorker::__destruct()
    Destroys a worker object */
 PHP_METHOD(GearmanWorker, __destruct) {
@@ -70,8 +83,6 @@ PHP_METHOD(GearmanWorker, __destruct) {
 		gearman_worker_free(&(intern->worker));
 		intern->flags &= ~GEARMAN_WORKER_OBJ_CREATED;
 	}
-
-	zval_dtor(&intern->cb_list);
 }
 /* }}} */
 
@@ -473,7 +484,7 @@ static void *_php_worker_function_callback(gearman_job_st *job,
                                                 void *context,
                                                 size_t *result_size,
                                                 gearman_return_t *ret_ptr) {
-        zval zjob, message;
+        zval zjob;
         gearman_job_obj *jobj;
         gearman_worker_cb_obj *worker_cb = (gearman_worker_cb_obj *)context;
         char *result = NULL;
@@ -516,9 +527,7 @@ static void *_php_worker_function_callback(gearman_job_st *job,
         if (EG(exception)) {
                 *ret_ptr = GEARMAN_WORK_EXCEPTION;
 
-                ZVAL_STRING(&message, "Unable to add worker function");
-
-                jobj->ret = gearman_job_send_exception(jobj->job, Z_STRVAL(message), Z_STRLEN(message));
+                jobj->ret = gearman_job_send_exception(jobj->job, "Unable to add worker function", sizeof("Unable to add worker function") - 1);
 
                 if (jobj->ret != GEARMAN_SUCCESS && jobj->ret != GEARMAN_IO_WAIT) {
                         php_error_docref(NULL, E_WARNING,  "Unable to add worker function: %s",
diff --git a/php_gearman_worker.h b/php_gearman_worker.h
index 91f5048..27f94cc 100644
--- a/php_gearman_worker.h
+++ b/php_gearman_worker.h
@@ -31,6 +31,7 @@ extern zend_class_entry *gearman_worker_ce;
 extern zend_object_handlers gearman_worker_obj_handlers;
 
 zend_object *gearman_worker_obj_new(zend_class_entry *ce);
+void gearman_worker_free_obj(zend_object *object);
 
 typedef struct {
         zval zname; /* name associated with callback */