# Segfault

- Thread: https://externals.io/message/19009
- Original archive: https://news-web.php.net/php.internals/19009
- Started by ScriptBlue@nyc.rr.com on 2005-09-15T20:54:45+00:00
- Messages: 10
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #19009 — ScriptBlue@nyc.rr.com — 2005-09-15T20:54:45+00:00

URL: https://externals.io/message/19009#19009

The following code segfaults after either I call die/exit or call
socketi_accept once again.
Can anyone spot anything working with it?

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_hello.h"
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#define IS_INVALID_SOCKET(a)   (a->bsd_socket < 0)
#define set_errno(a) (errno = a)

static
        ZEND_BEGIN_ARG_INFO(second_and_third_args_force_ref, 0)
                ZEND_ARG_PASS_INFO(0)
                ZEND_ARG_PASS_INFO(1)
                ZEND_ARG_PASS_INFO(1)
        ZEND_END_ARG_INFO();


static int le_socket = -1;
#define le_socket_name "Socket"
static socklen_t s_len = sizeof(struct sockaddr);

static function_entry hello_functions[] = {
    PHP_FE(hello_world, first_arg_force_ref)
    PHP_FE(socketi_accept, second_and_third_args_force_ref)
    {NULL, NULL, NULL}
};

/*--- */
PHP_MINFO_FUNCTION(hello)
{
        php_info_print_table_start();
        php_info_print_table_row(2, "Sockets Improved Support", "enabled");
        php_info_print_table_end();
}

PHP_RINIT_FUNCTION(hello)
{
        return SUCCESS;
}

PHP_RSHUTDOWN_FUNCTION(hello)
{
        return SUCCESS;
}
/*----*/

PHP_MINIT_FUNCTION(hello);
zend_module_entry hello_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    PHP_HELLO_WORLD_EXTNAME,
    hello_functions,
    PHP_MINIT(hello),
    NULL,
    PHP_RINIT(hello),
    PHP_RSHUTDOWN(hello),
    PHP_MINFO(hello),
#if ZEND_MODULE_API_NO >= 20010901
    PHP_HELLO_WORLD_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_HELLO
ZEND_GET_MODULE(hello)
#endif



#define PHP_SOCKETS_API
#if HAVE_SYS_SOCKET_H
  #include <sys/socket.h>
#endif
typedef int PHP_SOCKET;

typedef struct {
        PHP_SOCKET bsd_socket;
        int             type;
        int             error;
} php_socket;
#define le_socket_name "Socket"
//static int le_socket = 0;

static void php_destroy_socket(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
        php_socket *php_sock = (php_socket *) rsrc->ptr;

        close(php_sock->bsd_socket);
        efree(php_sock);
}


PHP_MINIT_FUNCTION(hello)
{
 le_socket = zend_fetch_list_dtor_id("Socket");
 //le_socket = zend_register_list_destructors_ex(, NULL, le_socket_name,
module_number);
}
ZEND_BEGIN_MODULE_GLOBALS(hello)
        int last_error;
        char *strerror_buf;
ZEND_END_MODULE_GLOBALS(hello)

PHP_FUNCTION(hello_world)
{
        zend_printf("%d--\n", le_socket);
  zval *buf;
        char            *recv_buf;
        int                     retval, len;
 long test;
//        long                    len, flags, php_sock_res;

//        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lzll",
&php_sock_res, &buf, &len, &flags) == FAILURE)
  //              return;
 test = NULL;
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &buf,
&test) == FAILURE)
                return;

 if(test != NULL)
  zend_printf("%ld", test);
        len = 300;
        recv_buf = emalloc(len + 1);
        memset(recv_buf, '\0', len + 1);

//        retval = recvz(recv_buf);
        char new_set[] = "=D!!";
        retval = strlen(new_set);
        memcpy(recv_buf, new_set, retval);
        recv_buf[retval] = '\0';
        zval_dtor(buf);

        Z_STRVAL_P(buf) = recv_buf;
        Z_STRLEN_P(buf) = retval;
        Z_TYPE_P(buf) = IS_STRING;
 zend_printf("(((((----------- %d -------------))))))))))", le_socket);
        RETURN_LONG(retval);
}


PHP_FUNCTION(socketi_accept)
{
 zend_printf("[init]");
 zval *sock, *remote_addr, *port;
 php_socket *php_sock, *new_sock;
 struct sockaddr_in sa;
 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|zz", &sock,
&remote_addr, &port) == FAILURE)
  return;
 ZEND_FETCH_RESOURCE(php_sock, php_socket *, &sock, -1, le_socket_name,
le_socket);
 int salen, addr_len;
 salen = sizeof(struct sockaddr_in);
 new_sock->bsd_socket = accept(php_sock->bsd_socket, &sa, &salen);
 switch(ZEND_NUM_ARGS())
 {
  case 3:
  {
   Z_TYPE_P(port) = IS_LONG;
   Z_LVAL_P(port) = ntohs(sa.sin_port);
  }
  case 2:
  {
   char *buf;
   addr_len = strlen(inet_ntoa(sa.sin_addr));
   buf = (char *) emalloc(addr_len + 1);
   zend_printf("[1]");
   memcpy(buf, inet_ntoa(sa.sin_addr), addr_len);
   zend_printf("[2]");
   buf[addr_len] = '\0';
   zval_dtor(remote_addr);
   zend_printf("[3]");

   Z_STRVAL_P(remote_addr) = buf;
   Z_STRLEN_P(remote_addr) = addr_len;
   Z_TYPE_P(remote_addr) = IS_STRING;
   efree(buf);
  }
  default:  //don't ask me how
  case 1:
   zend_printf("[4]");
   new_sock->error = 0;
   zend_printf("[5]");
 }
 ZEND_REGISTER_RESOURCE(return_value, new_sock, le_socket);
 zend_printf("RET!");

}

---

## #19012 — Sara Golemon — 2005-09-15T23:00:10+00:00

URL: https://externals.io/message/19009#19012 · In reply to: #19009

>  new_sock->bsd_socket = accept(php_sock->bsd_socket, &sa, &salen);
>
In all liklihood it's that.

Now.... In the nicest way possible, why don't I suggest that you CLEAN UP
YOUR CODE NEXT TIME!?!?!  You might have noticed that new_sock isn't alloc'd
if it wern't for all the comments and flat-out bad code you've got in there.

Thank you for calling, next in line please.

-Sara

---

## #19021 — ScriptBlue@nyc.rr.com — 2005-09-16T01:09:13+00:00

URL: https://externals.io/message/19009#19021 · In reply to: #19012

For some reason I can't malloc php_socket structs, and that's not where it
segfaults. The function works perfectly once. Then if I attempt to exit /
die or call that function again, it dies.
""Sara Golemon"" <pollita@php.net> wrote in message
news:00f301c5ba49$455192c0$5c8be5a9@ohr.berkeley.edu...
> > […]
> In all liklihood it's that.
>
> Now.... In the nicest way possible, why don't I suggest that you CLEAN UP
> YOUR CODE NEXT TIME!?!?!  You might have noticed that new_sock isn't
alloc'd
> if it wern't for all the comments and flat-out bad code you've got in
there.
>
> Thank you for calling, next in line please.
>
> -Sara

---

## #19022 — ScriptBlue@nyc.rr.com — 2005-09-16T01:21:26+00:00

URL: https://externals.io/message/19009#19022 · In reply to: #19012

That's not where it segfaults. The function works perfectly once. If I
attempt to exit /
die or call that function again, it segfaults.
However, I have noticed that if I do not use ZEND_REGISTER_RESOURCE the
program no longer segfaults.
And sorry for the comments, someone people don't write the final version of
a program on their first try.
""Sara Golemon"" <pollita@php.net> wrote in message
news:00f301c5ba49$455192c0$5c8be5a9@ohr.berkeley.edu...
> > […]
> In all liklihood it's that.
>
> Now.... In the nicest way possible, why don't I suggest that you CLEAN UP
> YOUR CODE NEXT TIME!?!?!  You might have noticed that new_sock isn't
alloc'd
> if it wern't for all the comments and flat-out bad code you've got in
there.
>
> Thank you for calling, next in line please.
>
> -Sara

---

## #19023 — Sara Golemon — 2005-09-16T02:09:57+00:00

URL: https://externals.io/message/19009#19023 · In reply to: #19022

> That's not where it segfaults. The function works perfectly once. If I
> attempt to exit /
> die or call that function again, it segfaults.
> However, I have noticed that if I do not use ZEND_REGISTER_RESOURCE the
> program no longer segfaults.
>
I didn't say that's where it segfaults, I said that's where your problem is. 
Just because you can write to a particular memory location once doesn't 
change the fact that the memory in question doesn't belong to your new_sock 
struct.  Your code is tacking a relevant piece of data and just throwing it 
out into the middle of the memory pool hoping it doesn't hit some swimmer in 
the head in the process.  Figure out why you can't malloc the struct first. 
That one is a very clear, unambiguous crash-causing bug.

> And sorry for the comments, someone people don't write the final version 
> of
> a program on their first try.
>
I'd doubt anyone does.  Writing well-indented code helps debugging though 
(both for you and for people you ask to take a second look).  Right now it's 
all just cluttered.  As my momma always told me, "If you'd clean up your 
room once in awhile, you might find what you're looking for."

And if my reply sounded harsh, it might have to do with the fact that you 
ignored my suggestions on how to implement zend_fetch_list_dtor_id().

-Sara

---

## #19063 — ScriptBlue@nyc.rr.com — 2005-09-16T21:50:16+00:00

URL: https://externals.io/message/19009#19063 · In reply to: #19023

Well I did try to use it in RINIT, but PHP just wasn't RINIT.... so I
figured why not put it in MINIT

""Sara Golemon"" <pollita@php.net> wrote in message
news:001901c5ba69$b6573c70$6c051fac@lighthammer...
> > […]
> I didn't say that's where it segfaults, I said that's where your problem
is.
> Just because you can write to a particular memory location once doesn't
> change the fact that the memory in question doesn't belong to your
new_sock
> struct.  Your code is tacking a relevant piece of data and just throwing
it
> out into the middle of the memory pool hoping it doesn't hit some swimmer
in
> the head in the process.  Figure out why you can't malloc the struct
first.
> That one is a very clear, unambiguous crash-causing bug.
>
> > […]
> I'd doubt anyone does.  Writing well-indented code helps debugging though
> (both for you and for people you ask to take a second look).  Right now
it's
> all just cluttered.  As my momma always told me, "If you'd clean up your
> room once in awhile, you might find what you're looking for."
>
> And if my reply sounded harsh, it might have to do with the fact that you
> ignored my suggestions on how to implement zend_fetch_list_dtor_id().
>
> -Sara

---

## #19064 — ScriptBlue@nyc.rr.com — 2005-09-16T22:06:45+00:00

URL: https://externals.io/message/19009#19064 · In reply to: #19023

Well I did try to use it in RINIT, but PHP just wasn't RINIT.... so I
figured why not put it in MINIT. And I solved the problem, I guess I should
have been more careful when reading the PHP API tutorials, I used malloc
instead of emalloc, so malloc was causing gcc to miscalculate its size or
make it quit with an error. Thank you for your help.

""Sara Golemon"" <pollita@php.net> wrote in message
news:001901c5ba69$b6573c70$6c051fac@lighthammer...
> > […]
> I didn't say that's where it segfaults, I said that's where your problem
is.
> Just because you can write to a particular memory location once doesn't
> change the fact that the memory in question doesn't belong to your
new_sock
> struct.  Your code is tacking a relevant piece of data and just throwing
it
> out into the middle of the memory pool hoping it doesn't hit some swimmer
in
> the head in the process.  Figure out why you can't malloc the struct
first.
> That one is a very clear, unambiguous crash-causing bug.
>
> > […]
> I'd doubt anyone does.  Writing well-indented code helps debugging though
> (both for you and for people you ask to take a second look).  Right now
it's
> all just cluttered.  As my momma always told me, "If you'd clean up your
> room once in awhile, you might find what you're looking for."
>
> And if my reply sounded harsh, it might have to do with the fact that you
> ignored my suggestions on how to implement zend_fetch_list_dtor_id().
>
> -Sara

---

## #19067 — Hartmut Holzgraefe — 2005-09-17T05:54:40+00:00

URL: https://externals.io/message/19009#19067 · In reply to: #19064

RG wrote:
> Well I did try to use it in RINIT, but PHP just wasn't RINIT.... so I
> figured why not put it in MINIT. 
...
 > I used malloc
> instead of emalloc, so malloc was causing gcc to miscalculate its size or
> make it quit with an error. 

both claims above don't make *any* sense to me, making me think
you still really do not know what you are doing :(

---

## #19068 — ScriptBlue@nyc.rr.com — 2005-09-17T17:15:54+00:00

URL: https://externals.io/message/19009#19068 · In reply to: #19067

> both claims above don't make *any* sense to me, making me think
> you still really do not know what you are doing :(
O_O, wow, sorry...
I did not write that like that......
What I meant to say was that I did use  zend_fetch_list_dtor_id in RINIT at
first, but I noticed that PHP was not calling RINIT. So then I migrated it
MINIT, which is called when the module is loaded.

As for malloc/emalloc, I tried using malloc(sizeof(struct php_socket));
which did not work because gcc was erroring with "Incomplete datatype". I
then re-read the Zend API function list and came across emalloc, which I had
omitted when I first read it. So once I used emalloc, it worked.

---

## #19069 — Sara Golemon — 2005-09-17T17:50:37+00:00

URL: https://externals.io/message/19009#19069 · In reply to: #19068

> What I meant to say was that I did use  zend_fetch_list_dtor_id in RINIT 
> at
> first, but I noticed that PHP was not calling RINIT. So then I migrated it
> MINIT, which is called when the module is loaded.
>
Doubtful...  PHP calls every module's RINIT at the start of every request. 
If you were "testing" RINIT by launching something like `php -m` or `php -i` 
or something then sure RINIT wouldn't be called.  There's no actual request 
involved.  In a real script execute it most certainly would call RINIT.

> As for malloc/emalloc, I tried using malloc(sizeof(struct php_socket));
> which did not work because gcc was erroring with "Incomplete datatype". I
> then re-read the Zend API function list and came across emalloc, which I 
> had
> omitted when I first read it. So once I used emalloc, it worked.
>
The malloc/emalloc issue is genuine enough in that yes, you do need to be 
using the emalloc() family over the system malloc allocators (except in rare 
cases involving persistency).

The larger issue of the incomplete type comes from the fact that the form of 
your structure declaration means you'll want to get your size from 
sizeof(php_socket) not sizeof(struct php_socket).

typedef struct {
        PHP_SOCKET bsd_socket;
        int             type;
        int             error;
} php_socket;
