From 9198faa67fc2e0594bc1aff01b4eadb40835ac68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Fri, 8 May 2020 17:18:39 +0200 Subject: Convert resource to object in Sysvmsg Closes GH-5546 --- ext/sysvmsg/sysvmsg.c | 106 +++++++++++++++++++++++++++--------------- ext/sysvmsg/sysvmsg.stub.php | 40 ++++++---------- ext/sysvmsg/sysvmsg_arginfo.h | 17 ++++--- ext/sysvmsg/tests/003.phpt | 3 +- ext/sysvmsg/tests/005.phpt | 8 ++-- 5 files changed, 100 insertions(+), 74 deletions(-) (limited to 'ext') diff --git a/ext/sysvmsg/sysvmsg.c b/ext/sysvmsg/sysvmsg.c index 9721193945..e44bb58aea 100644 --- a/ext/sysvmsg/sysvmsg.c +++ b/ext/sysvmsg/sysvmsg.c @@ -25,6 +25,7 @@ #include "sysvmsg_arginfo.h" #include "ext/standard/php_var.h" #include "zend_smart_str.h" +#include "Zend/zend_interfaces.h" #include #include @@ -36,6 +37,7 @@ PHP_MINFO_FUNCTION(sysvmsg); typedef struct { key_t key; zend_long id; + zend_object std; } sysvmsg_queue_t; struct php_msgbuf { @@ -50,9 +52,6 @@ struct php_msgbuf { #define PHP_MSG_NOERROR 2 #define PHP_MSG_EXCEPT 4 -/* True global resources - no need for thread safety here */ -static int le_sysvmsg; - /* {{{ sysvmsg_module_entry */ zend_module_entry sysvmsg_module_entry = { @@ -73,17 +72,58 @@ zend_module_entry sysvmsg_module_entry = { ZEND_GET_MODULE(sysvmsg) #endif -static void sysvmsg_release(zend_resource *rsrc) +/* SysvMessageQueue class */ + +zend_class_entry *sysvmsg_queue_ce; +static zend_object_handlers sysvmsg_queue_object_handlers; + +static inline sysvmsg_queue_t *sysvmsg_queue_from_obj(zend_object *obj) { + return (sysvmsg_queue_t *)((char *)(obj) - XtOffsetOf(sysvmsg_queue_t, std)); +} + +#define Z_SYSVMSG_QUEUE_P(zv) sysvmsg_queue_from_obj(Z_OBJ_P(zv)) + +static zend_object *sysvmsg_queue_create_object(zend_class_entry *class_type) { + sysvmsg_queue_t *intern = zend_object_alloc(sizeof(sysvmsg_queue_t), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &sysvmsg_queue_object_handlers; + + return &intern->std; +} + +static zend_function *sysvmsg_queue_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct SysvMessageQueue, use msg_get_queue() instead"); + return NULL; +} + +static void sysvmsg_queue_free_obj(zend_object *object) { - sysvmsg_queue_t *mq = (sysvmsg_queue_t *) rsrc->ptr; - efree(mq); + sysvmsg_queue_t *sysvmsg_queue = sysvmsg_queue_from_obj(object); + + zend_object_std_dtor(&sysvmsg_queue->std); } +/* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(sysvmsg) { - le_sysvmsg = zend_register_list_destructors_ex(sysvmsg_release, NULL, "sysvmsg queue", module_number); + zend_class_entry ce; + INIT_CLASS_ENTRY(ce, "SysvMessageQueue", class_SysvMessageQueue_methods); + sysvmsg_queue_ce = zend_register_internal_class(&ce); + sysvmsg_queue_ce->ce_flags |= ZEND_ACC_FINAL; + sysvmsg_queue_ce->create_object = sysvmsg_queue_create_object; + sysvmsg_queue_ce->serialize = zend_class_serialize_deny; + sysvmsg_queue_ce->unserialize = zend_class_unserialize_deny; + + memcpy(&sysvmsg_queue_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + sysvmsg_queue_object_handlers.offset = XtOffsetOf(sysvmsg_queue_t, std); + sysvmsg_queue_object_handlers.free_obj = sysvmsg_queue_free_obj; + sysvmsg_queue_object_handlers.get_constructor = sysvmsg_queue_get_constructor; + sysvmsg_queue_object_handlers.clone_obj = NULL; + REGISTER_LONG_CONSTANT("MSG_IPC_NOWAIT", PHP_MSG_IPC_NOWAIT, CONST_PERSISTENT|CONST_CS); REGISTER_LONG_CONSTANT("MSG_EAGAIN", EAGAIN, CONST_PERSISTENT|CONST_CS); REGISTER_LONG_CONSTANT("MSG_ENOMSG", ENOMSG, CONST_PERSISTENT|CONST_CS); @@ -103,7 +143,7 @@ PHP_MINFO_FUNCTION(sysvmsg) } /* }}} */ -/* {{{ proto bool msg_set_queue(resource queue, array data) +/* {{{ proto bool msg_set_queue(SysvMessageQueue queue, array data) Set information for a message queue */ PHP_FUNCTION(msg_set_queue) { @@ -113,13 +153,11 @@ PHP_FUNCTION(msg_set_queue) RETVAL_FALSE; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra", &queue, &data) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oa", &queue, sysvmsg_queue_ce, &data) == FAILURE) { RETURN_THROWS(); } - if ((mq = (sysvmsg_queue_t *)zend_fetch_resource(Z_RES_P(queue), "sysvmsg queue", le_sysvmsg)) == NULL) { - RETURN_THROWS(); - } + mq = Z_SYSVMSG_QUEUE_P(queue); if (msgctl(mq->id, IPC_STAT, &stat) == 0) { zval *item; @@ -144,7 +182,7 @@ PHP_FUNCTION(msg_set_queue) } /* }}} */ -/* {{{ proto array msg_stat_queue(resource queue) +/* {{{ proto array msg_stat_queue(SysvMessageQueue queue) Returns information about a message queue */ PHP_FUNCTION(msg_stat_queue) { @@ -154,13 +192,11 @@ PHP_FUNCTION(msg_stat_queue) RETVAL_FALSE; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &queue) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &queue, sysvmsg_queue_ce) == FAILURE) { RETURN_THROWS(); } - if ((mq = (sysvmsg_queue_t *)zend_fetch_resource(Z_RES_P(queue), "sysvmsg queue", le_sysvmsg)) == NULL) { - RETURN_THROWS(); - } + mq = Z_SYSVMSG_QUEUE_P(queue); if (msgctl(mq->id, IPC_STAT, &stat) == 0) { array_init(return_value); @@ -197,7 +233,7 @@ PHP_FUNCTION(msg_queue_exists) } /* }}} */ -/* {{{ proto resource msg_get_queue(int key [, int perms]) +/* {{{ proto SysvMessageQueue msg_get_queue(int key [, int perms]) Attach to a message queue */ PHP_FUNCTION(msg_get_queue) { @@ -209,7 +245,8 @@ PHP_FUNCTION(msg_get_queue) RETURN_THROWS(); } - mq = (sysvmsg_queue_t *) emalloc(sizeof(sysvmsg_queue_t)); + object_init_ex(return_value, sysvmsg_queue_ce); + mq = Z_SYSVMSG_QUEUE_P(return_value); mq->key = key; mq->id = msgget(key, 0); @@ -218,28 +255,25 @@ PHP_FUNCTION(msg_get_queue) mq->id = msgget(key, IPC_CREAT | IPC_EXCL | perms); if (mq->id < 0) { php_error_docref(NULL, E_WARNING, "Failed for key 0x" ZEND_XLONG_FMT ": %s", key, strerror(errno)); - efree(mq); + zval_ptr_dtor(return_value); RETURN_FALSE; } } - ZVAL_COPY_VALUE(return_value, zend_list_insert(mq, le_sysvmsg)); } /* }}} */ -/* {{{ proto bool msg_remove_queue(resource queue) +/* {{{ proto bool msg_remove_queue(SysvMessageQueue queue) Destroy the queue */ PHP_FUNCTION(msg_remove_queue) { zval *queue; sysvmsg_queue_t *mq = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &queue) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &queue, sysvmsg_queue_ce) == FAILURE) { RETURN_THROWS(); } - if ((mq = (sysvmsg_queue_t *)zend_fetch_resource(Z_RES_P(queue), "sysvmsg queue", le_sysvmsg)) == NULL) { - RETURN_THROWS(); - } + mq = Z_SYSVMSG_QUEUE_P(queue); if (msgctl(mq->id, IPC_RMID, NULL) == 0) { RETVAL_TRUE; @@ -249,7 +283,7 @@ PHP_FUNCTION(msg_remove_queue) } /* }}} */ -/* {{{ proto mixed msg_receive(resource queue, int desiredmsgtype, int &msgtype, int maxsize, mixed &message [, bool unserialize=true [, int flags=0 [, int &errorcode]]]) +/* {{{ proto mixed msg_receive(SysvMessageQueue queue, int desiredmsgtype, int &msgtype, int maxsize, mixed &message [, bool unserialize=true [, int flags=0 [, int &errorcode]]]) Send a message of type msgtype (must be > 0) to a message queue */ PHP_FUNCTION(msg_receive) { @@ -263,8 +297,8 @@ PHP_FUNCTION(msg_receive) RETVAL_FALSE; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlzlz|blz", - &queue, &desiredmsgtype, &out_msgtype, &maxsize, + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olzlz|blz", + &queue, sysvmsg_queue_ce, &desiredmsgtype, &out_msgtype, &maxsize, &out_message, &do_unserialize, &flags, &zerrcode) == FAILURE) { RETURN_THROWS(); } @@ -291,9 +325,7 @@ PHP_FUNCTION(msg_receive) } } - if ((mq = (sysvmsg_queue_t *)zend_fetch_resource(Z_RES_P(queue), "sysvmsg queue", le_sysvmsg)) == NULL) { - RETURN_THROWS(); - } + mq = Z_SYSVMSG_QUEUE_P(queue); messagebuffer = (struct php_msgbuf *) safe_emalloc(maxsize, 1, sizeof(struct php_msgbuf)); @@ -335,7 +367,7 @@ PHP_FUNCTION(msg_receive) } /* }}} */ -/* {{{ proto bool msg_send(resource queue, int msgtype, mixed message [, bool serialize=true [, bool blocking=true [, int errorcode]]]) +/* {{{ proto bool msg_send(SysvMessageQueue queue, int msgtype, mixed message [, bool serialize=true [, bool blocking=true [, int errorcode]]]) Send a message of type msgtype (must be > 0) to a message queue */ PHP_FUNCTION(msg_send) { @@ -349,14 +381,12 @@ PHP_FUNCTION(msg_send) RETVAL_FALSE; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz|bbz", - &queue, &msgtype, &message, &do_serialize, &blocking, &zerror) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olz|bbz", + &queue, sysvmsg_queue_ce, &msgtype, &message, &do_serialize, &blocking, &zerror) == FAILURE) { RETURN_THROWS(); } - if ((mq = (sysvmsg_queue_t *)zend_fetch_resource(Z_RES_P(queue), "sysvmsg queue", le_sysvmsg)) == NULL) { - RETURN_THROWS(); - } + mq = Z_SYSVMSG_QUEUE_P(queue); if (do_serialize) { smart_str msg_var = {0}; diff --git a/ext/sysvmsg/sysvmsg.stub.php b/ext/sysvmsg/sysvmsg.stub.php index 5bbe100ca6..f6c4d07e43 100644 --- a/ext/sysvmsg/sysvmsg.stub.php +++ b/ext/sysvmsg/sysvmsg.stub.php @@ -2,30 +2,20 @@ /** @generate-function-entries */ -/** @return resource|false */ -function msg_get_queue(int $key, int $perms = 0666) {} - -/** - * @param resource $queue - */ -function msg_send($queue, int $msgtype, $message, bool $serialize = true, bool $blocking = true, &$errorcode = null): bool {} - -/** - * @param resource $queue - */ -function msg_receive($queue, int $desiredmsgtype, &$msgtype, int $maxsize, &$message, bool $unserialize = true, int $flags = 0, &$errorcode = null): bool {} - -/** - * @param resource $queue - */ -function msg_remove_queue($queue): bool {} - -/** @param resource $queue */ -function msg_stat_queue($queue): array|false {} - -/** - * @param resource $queue - */ -function msg_set_queue($queue, array $data): bool {} +final class SysvMessageQueue +{ +} + +function msg_get_queue(int $key, int $perms = 0666): SysvMessageQueue|false {} + +function msg_send(SysvMessageQueue $queue, int $msgtype, $message, bool $serialize = true, bool $blocking = true, &$errorcode = null): bool {} + +function msg_receive(SysvMessageQueue $queue, int $desiredmsgtype, &$msgtype, int $maxsize, &$message, bool $unserialize = true, int $flags = 0, &$errorcode = null): bool {} + +function msg_remove_queue(SysvMessageQueue $queue): bool {} + +function msg_stat_queue(SysvMessageQueue $queue): array|false {} + +function msg_set_queue(SysvMessageQueue $queue, array $data): bool {} function msg_queue_exists(int $key): bool {} diff --git a/ext/sysvmsg/sysvmsg_arginfo.h b/ext/sysvmsg/sysvmsg_arginfo.h index 88ec5af6b8..30d08d968c 100644 --- a/ext/sysvmsg/sysvmsg_arginfo.h +++ b/ext/sysvmsg/sysvmsg_arginfo.h @@ -1,12 +1,12 @@ /* This is a generated file, edit the .stub.php file instead. */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_msg_get_queue, 0, 0, 1) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_msg_get_queue, 0, 1, SysvMessageQueue, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, perms, IS_LONG, 0, "0666") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_send, 0, 3, _IS_BOOL, 0) - ZEND_ARG_INFO(0, queue) + ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0) ZEND_ARG_TYPE_INFO(0, msgtype, IS_LONG, 0) ZEND_ARG_INFO(0, message) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, serialize, _IS_BOOL, 0, "true") @@ -15,7 +15,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_send, 0, 3, _IS_BOOL, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_receive, 0, 5, _IS_BOOL, 0) - ZEND_ARG_INFO(0, queue) + ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0) ZEND_ARG_TYPE_INFO(0, desiredmsgtype, IS_LONG, 0) ZEND_ARG_INFO(1, msgtype) ZEND_ARG_TYPE_INFO(0, maxsize, IS_LONG, 0) @@ -26,15 +26,15 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_receive, 0, 5, _IS_BOOL, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_remove_queue, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, queue) + ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_msg_stat_queue, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) - ZEND_ARG_INFO(0, queue) + ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_set_queue, 0, 2, _IS_BOOL, 0) - ZEND_ARG_INFO(0, queue) + ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0) ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -62,3 +62,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(msg_queue_exists, arginfo_msg_queue_exists) ZEND_FE_END }; + + +static const zend_function_entry class_SysvMessageQueue_methods[] = { + ZEND_FE_END +}; diff --git a/ext/sysvmsg/tests/003.phpt b/ext/sysvmsg/tests/003.phpt index 66ff046dd0..d447bf8f72 100644 --- a/ext/sysvmsg/tests/003.phpt +++ b/ext/sysvmsg/tests/003.phpt @@ -18,7 +18,8 @@ echo "Done\n"; ?> --EXPECTF-- bool(false) -resource(%d) of type (sysvmsg queue) +object(SysvMessageQueue)#1 (0) { +} bool(true) bool(true) bool(false) diff --git a/ext/sysvmsg/tests/005.phpt b/ext/sysvmsg/tests/005.phpt index 68323e9a30..727c42db66 100644 --- a/ext/sysvmsg/tests/005.phpt +++ b/ext/sysvmsg/tests/005.phpt @@ -7,7 +7,7 @@ sysvmsg functions on non-existing queue $tests = array(null, 'foo'); -foreach ($tests as $q) { +foreach ($tests as $i => $q) { if ($q === null) { do { @@ -17,7 +17,7 @@ foreach ($tests as $q) { $q = msg_get_queue($id) or die("Failed to create queue"); msg_remove_queue($q) or die("Failed to close queue"); - echo "Using '$q' as queue resource:\n"; + echo "Iteration " . ($i + 1) . ":\n"; $errno = 0; @@ -37,7 +37,7 @@ foreach ($tests as $q) { echo "Done\n"; ?> --EXPECTF-- -Using 'Resource id #4' as queue resource: +Iteration 1: bool(false) bool(false) bool(false) @@ -49,7 +49,7 @@ bool(false) Warning: msg_send(): msgsnd failed: Invalid argument in %s on line %d bool(false) bool(true) -Using 'Resource id #5' as queue resource: +Iteration 2: bool(false) bool(false) bool(false) -- cgit v1.2.1