]> granicus.if.org Git - php/commitdiff
- shmop_open has a new flag for read/write access, 'w'
authorYasuo Ohgaki <yohgaki@php.net>
Wed, 9 Jan 2002 08:02:21 +0000 (08:02 +0000)
committerYasuo Ohgaki <yohgaki@php.net>
Wed, 9 Jan 2002 08:02:21 +0000 (08:02 +0000)
- eliminated a segfault when trying to write to a SHM_RDONLY segment
- eliminated a segfault when an invalid flag which starts with 'a' or 'c' is passed
- updated creators' email addresses
- changed error messages to say shmop_* instead of shm* to correspond with new shmop_* function names
Patch by Ilia Alshanetsky (ilia@prohost.org)
# Please test :)

ext/shmop/README
ext/shmop/config.m4
ext/shmop/php_shmop.h
ext/shmop/shmop.c

index 381ad9cbc36aa706612ebc9a3d5c2ef9c4180ac5..d1cc5abc2b4e0a1a7aca4bb1f82cde9ffd052d9b 100644 (file)
@@ -1,31 +1,35 @@
-last update sept 3, 2000 (slavapl@mailandnews.com/iliaa@home.com)
+last update Jan 2, 2002 (hackie@prohost.org/ilia@prohost.org)
 
 Shared Memory Operations Extension to PHP4
 
-       While developing a search deamon we needed the php based front end
-       to communicate the deamon via SHM. Now, PHP already had a shared memory
+       While developing a search deamon we needed a php based front end
+       to communicate the deamon via SHM. PHP already had a shared memory
        extention (sysvshm) written by Christian Cartus <cartus@atrior.de>,
-       unfortunatly this extention was designed with PHP only in mind, and
+       unfortunatly this extention was designed with PHP only in mind and
        offers high level features which are extremly bothersome for basic SHM
-       we had in mind.  After spending a day trying to reverse engeener figure
+       we had in mind.  After spending a day trying to reverse engineer and figure
        out the format of sysvshm we decided that it would be much easier to
        add our own extention to php for simple SHM operations, we were right :)). 
 
 the functions are:
        
-int shm_open(int key, string flags, int mode, int size)
+int shmop_open(int key, string flags, int mode, int size)
        
        key             - the key of/for the shared memory block
-       flags           - 2 flags are avalible 
-                               a for access  (sets IPC_EXCL)
-                               c for create  (sets IPC_CREATE)
+       flags           - 4 flags are avalible 
+                               a for read only access (sets SHM_RDONLY)
+                               w for read & write access
+                               c create or open an existing segment (sets IPC_CREATE)
+                               n create a new segment and fail if one already exists under same name (sets IPC_CREATE|IPC_EXCL)
+                               (the n flag is mostly useful for security perpouses, so that you don't end up opening a faked segment 
+                               if someone guesses your key)
        mode            - acsess mode same as for a file (0644) for example
        size            - size of the block in bytes
        
        returns an indentifier
        
 
-char shm_read(int shmid, int start, int count)
+char shmop_read(int shmid, int start, int count)
 
        shmid           - shmid from which to read
        start           - offset from which to start reading
@@ -33,7 +37,7 @@ char shm_read(int shmid, int start, int count)
        
        returns the data read
 
-int shm_write(int shmid, string data, int offset)
+int shmop_write(int shmid, string data, int offset)
 
        shmid           - shmid from which to read
        data            - string to put into shared memory
@@ -41,14 +45,14 @@ int shm_write(int shmid, string data, int offset)
        
        returns bytes written
        
-int shm_size(int shmid)
+int shmop_size(int shmid)
 
        shmid           - shmid for which to return the size
        
        returns the size in bytes of the shm segment
        
        
-int shm_delete(int shmid)
+int shmop_delete(int shmid)
 
        marks the segment for deletion, the segment will be deleted when all processes mapping it will detach
 
@@ -56,7 +60,7 @@ int shm_delete(int shmid)
        
        returns 1 if all ok, zero on failure
        
-int shm_close(int shmid)
+int shmop_close(int shmid)
 
        shmid           - shmid which to close
        
index e3044af35e1074362203f08ca43c1fddb1ff525b..1a9ca6adade4b915e431a3c974d3cf37e1a6c750 100644 (file)
@@ -1,7 +1,4 @@
-dnl
 dnl $Id$
-dnl
-
 PHP_ARG_ENABLE(shmop, whether to enable shmop support, 
 [  --enable-shmop          Enable shmop support])
 
index 78eb7e06e82dc6e6379348e87f21fc993fbdf69b..791289dd09e84ec739d5c8d3da89b481927b8f88 100644 (file)
@@ -52,6 +52,7 @@ struct php_shmop
        int shmid;
        key_t key;
        int shmflg;
+       int shmatflg;
        char *addr;
        int size;
 };
index f54ab1f81cf9bc1d424411eb69f6f77c392a991f..0c8c0c2cc527918ed20d2cdffae5b3e6263986e1 100644 (file)
@@ -1,6 +1,6 @@
 /*
    +----------------------------------------------------------------------+
-   | PHP Version 4                                                        |
+   | PHP version 4                                                        |
    +----------------------------------------------------------------------+
    | Copyright (c) 1997-2002 The PHP Group                                |
    +----------------------------------------------------------------------+
@@ -12,8 +12,8 @@
    | obtain it through the world-wide-web, please send a note to          |
    | license@php.net so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+
-   | Authors: Slava Poliakov (slavapl@mailandnews.com)                    |
-   |          Ilia Alshanetsky (iliaa@home.com)                           |
+   | Authors: Slava Poliakov (hackie@prohost.org)                        |
+   |          Ilia Alshanetsky (ilia@prohost.org)                         |
    +----------------------------------------------------------------------+
  */
 /* $Id$ */
@@ -125,7 +125,6 @@ PHP_FUNCTION(shmop_open)
        struct php_shmop *shmop;        
        struct shmid_ds shm;
        int rsid;
-       int shmflg=0;
 
        if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &key, &flags, &mode, &size) == FAILURE) {
                WRONG_PARAM_COUNT;
@@ -139,40 +138,56 @@ PHP_FUNCTION(shmop_open)
        shmop = emalloc(sizeof(struct php_shmop));
        memset(shmop, 0, sizeof(struct php_shmop));
 
-       shmop->key = Z_LVAL_PP(key);
-       shmop->shmflg |= Z_LVAL_PP(mode);
+       shmop->key = (*key)->value.lval;
+       shmop->shmflg |= (*mode)->value.lval;
 
-       if (memchr(Z_STRVAL_PP(flags), 'a', Z_STRLEN_PP(flags))) {
-               shmflg = SHM_RDONLY;
-               shmop->shmflg |= IPC_EXCL;
-       } 
-       else if (memchr(Z_STRVAL_PP(flags), 'c', Z_STRLEN_PP(flags))) {
-               shmop->shmflg |= IPC_CREAT;
-               shmop->size = Z_LVAL_PP(size);
-       }
-       else {
-               php_error(E_WARNING, "shmopen: access mode invalid");
-               efree(shmop);
+       if( (*flags)->value.str.len != 1 ) {
+               php_error(E_WARNING, "shmop_open: invalid flag");
                RETURN_FALSE;
        }
 
+       switch( (*flags)->value.str.val[0] ) 
+       {
+               case 'a':
+                       shmop->shmatflg |= SHM_RDONLY;
+                       break;
+               case 'c':
+                       shmop->shmflg |= IPC_CREAT;
+                       shmop->size = (*size)->value.lval;
+                       break;
+               case 'n':
+                       shmop->shmflg |= (IPC_CREAT|IPC_EXCL);
+                       shmop->size = (*size)->value.lval;
+                       break;  
+               case 'w':
+                       /* noop 
+                               shm segment is being opened for read & write
+                               will fail if segment does not exist
+                       */
+                       break;
+               default:
+                       php_error(E_WARNING, "shmop_open: invalid access mode");
+                       efree(shmop);
+                       RETURN_FALSE;
+       }
+
        shmop->shmid = shmget(shmop->key, shmop->size, shmop->shmflg);
        if (shmop->shmid == -1) {
-               php_error(E_WARNING, "shmopen: can't get the block");
+               php_error(E_WARNING, "shmop_open: unable to attach or create shm segment");
                efree(shmop);
                RETURN_FALSE;
        }
 
        if (shmctl(shmop->shmid, IPC_STAT, &shm)) {
                efree(shmop);
-               php_error(E_WARNING, "shmopen: can't get information on the block");
+               php_error(E_WARNING, "shmop_open: unable to get shm segment information");
                RETURN_FALSE;
        }       
 
-       shmop->addr = shmat(shmop->shmid, 0, shmflg);
+       shmop->addr = shmat(shmop->shmid, 0, shmop->shmatflg);
        if (shmop->addr == (char*) -1) {
                efree(shmop);
-               php_error(E_WARNING, "shmopen: can't attach the memory block");
+               php_error(E_WARNING, "shmop_open: unable to attach to shm segment");
                RETURN_FALSE;
        }
 
@@ -202,30 +217,30 @@ PHP_FUNCTION(shmop_read)
        convert_to_long_ex(start);
        convert_to_long_ex(count);
 
-       shmop = zend_list_find(Z_LVAL_PP(shmid), &type);        
+       shmop = zend_list_find((*shmid)->value.lval, &type);    
 
        if (!shmop) {
-               php_error(E_WARNING, "shmread: can't find this segment");
+               php_error(E_WARNING, "shmop_read: can't find this segment");
                RETURN_FALSE;
        }
 
-       if (Z_LVAL_PP(start) < 0 || Z_LVAL_PP(start) > shmop->size) {
-               php_error(E_WARNING, "shmread: start is out of range");
+       if ((*start)->value.lval < 0 || (*start)->value.lval > shmop->size) {
+               php_error(E_WARNING, "shmop_read: start is out of range");
                RETURN_FALSE;
        }
 
-       if ((Z_LVAL_PP(start)+Z_LVAL_PP(count)) > shmop->size) {
-               php_error(E_WARNING, "shmread: count is out of range");
+       if (((*start)->value.lval+(*count)->value.lval) > shmop->size) {
+               php_error(E_WARNING, "shmop_read: count is out of range");
                RETURN_FALSE;
        }
 
-       if (Z_LVAL_PP(count) < 0 ){
-               php_error(E_WARNING, "shmread: count is out of range");
+       if ((*count)->value.lval < 0 ){
+               php_error(E_WARNING, "shmop_read: count is out of range");
                RETURN_FALSE;
        }
 
-       startaddr = shmop->addr + Z_LVAL_PP(start);
-       bytes = Z_LVAL_PP(count) ? Z_LVAL_PP(count) : shmop->size-Z_LVAL_PP(start);
+       startaddr = shmop->addr + (*start)->value.lval;
+       bytes = (*count)->value.lval ? (*count)->value.lval : shmop->size-(*start)->value.lval;
 
        return_string = emalloc(bytes);
        memcpy(return_string, startaddr, bytes);
@@ -246,13 +261,13 @@ PHP_FUNCTION(shmop_close)
                WRONG_PARAM_COUNT;
        }
 
-       shmop = zend_list_find(Z_LVAL_PP(shmid), &type);
+       shmop = zend_list_find((*shmid)->value.lval, &type);
 
        if (!shmop) {
-               php_error(E_WARNING, "shmclose: no such shmid");
+               php_error(E_WARNING, "shmop_close: no such shmid");
                RETURN_FALSE;
        }
-       zend_list_delete(Z_LVAL_PP(shmid));
+       zend_list_delete((*shmid)->value.lval);
 }
 /* }}} */
 
@@ -270,10 +285,10 @@ PHP_FUNCTION(shmop_size)
 
        convert_to_long_ex(shmid);
 
-       shmop = zend_list_find(Z_LVAL_PP(shmid), &type);
+       shmop = zend_list_find((*shmid)->value.lval, &type);
 
        if (!shmop) {
-               php_error(E_WARNING, "shmsize: no such segment");
+               php_error(E_WARNING, "shmop_size: no such segment");
                RETURN_FALSE;
        }
 
@@ -298,20 +313,25 @@ PHP_FUNCTION(shmop_write)
        convert_to_string_ex(data);
        convert_to_long_ex(offset);
 
-       shmop = zend_list_find(Z_LVAL_PP(shmid), &type);
+       shmop = zend_list_find((*shmid)->value.lval, &type);
 
        if (!shmop) {
-               php_error(E_WARNING, "shmwrite: error no such segment");
+               php_error(E_WARNING, "shmop_write: error no such segment");
+               RETURN_FALSE;
+       }
+
+       if( (shmop->shmatflg&SHM_RDONLY) == SHM_RDONLY ) {
+               php_error(E_WARNING, "shmop_write: trying to write to a read only segment");
                RETURN_FALSE;
        }
 
-       if ( Z_LVAL_PP(offset) > shmop->size ) {
-               php_error(E_WARNING, "shmwrite: offset out of range");
+       if ( (*offset)->value.lval > shmop->size ) {
+               php_error(E_WARNING, "shmop_write: offset out of range");
                RETURN_FALSE;
        }
 
-       writesize = (Z_STRLEN_PP(data)<shmop->size-Z_LVAL_PP(offset)) ? Z_STRLEN_PP(data) : shmop->size-Z_LVAL_PP(offset);      
-       memcpy(shmop->addr+Z_LVAL_PP(offset), Z_STRVAL_PP(data), writesize);
+       writesize = ((*data)->value.str.len<shmop->size-(*offset)->value.lval) ? (*data)->value.str.len : shmop->size-(*offset)->value.lval;    
+       memcpy(shmop->addr+(*offset)->value.lval, (*data)->value.str.val, writesize);
 
        RETURN_LONG(writesize);
 }
@@ -331,15 +351,15 @@ PHP_FUNCTION(shmop_delete)
 
        convert_to_long_ex(shmid);
 
-       shmop = zend_list_find(Z_LVAL_PP(shmid), &type);
+       shmop = zend_list_find((*shmid)->value.lval, &type);
 
        if (!shmop) {
-               php_error(E_WARNING, "shmdelete: error no such segment");
+               php_error(E_WARNING, "shmop_delete: error no such segment");
                RETURN_FALSE;
        }
 
        if (shmctl(shmop->shmid, IPC_RMID, NULL)) {
-               php_error(E_WARNING, "shmdelete: can't mark segment for deletion (are you the owner?)");
+               php_error(E_WARNING, "shmop_delete: can't mark segment for deletion (are you the owner?)");
                RETURN_FALSE;
        }