]> granicus.if.org Git - php/commitdiff
Convert resource to object in Sysvmsg
authorMáté Kocsis <kocsismate@woohoolabs.com>
Fri, 8 May 2020 15:18:39 +0000 (17:18 +0200)
committerMáté Kocsis <kocsismate@woohoolabs.com>
Thu, 14 May 2020 10:56:06 +0000 (12:56 +0200)
Closes GH-5546

UPGRADING
ext/sysvmsg/sysvmsg.c
ext/sysvmsg/sysvmsg.stub.php
ext/sysvmsg/sysvmsg_arginfo.h
ext/sysvmsg/tests/003.phpt
ext/sysvmsg/tests/005.phpt

index 4bc75b2908015e4120c79124bc445c18372820e6..05929c548b6ee35fe7e5182b407496d1417433a0 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -418,6 +418,11 @@ PHP 8.0 UPGRADE NOTES
     explicit setlocale() call is now always required if you wish to change any
     locale component from the default.
 
+- Sysvmsg:
+  . msg_get_queue() will now return an SysvMessageQueue object rather than a resource.
+    Return value checks using is_resource() should be replaced with checks
+    for `false`.
+
 - Sysvsem:
   . sem_get() will now return an SysvSemaphore object rather than a resource.
     Return value checks using is_resource() should be replaced with checks
index 9721193945a29fc90290a14f9ca39455a21917d4..e44bb58aeae8fe5a4ea929e1caad486d1e9c9e1a 100644 (file)
@@ -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 <sys/types.h>
 #include <sys/ipc.h>
@@ -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};
index 5bbe100ca625e79736441905f73f81f5750a09fd..f6c4d07e438cb98129fb5e4c88bab019085a21f7 100644 (file)
@@ -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 {}
index 88ec5af6b8f925d19874d345fbf37fd047c6bd01..30d08d968c7e312979f8131a1cdec2a75a431495 100644 (file)
@@ -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
+};
index 66ff046dd03a4c4c0fe81c224dde937b76153a0f..d447bf8f72cbd1d2864b3447dc886d8eb21ccb3b 100644 (file)
@@ -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)
index 68323e9a308aa1b0695a6a916ab96bf855533ff7..727c42db66bd67c5a910e42c74d926f01a6f1300 100644 (file)
@@ -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)