In testing PHP7 beyond just the default extensions, I am noticing that
ext/imap is segfaulting on almost every test. I tracked it down to this
code in ext/imap/php_imap.c:

/* {{{ imap_do_open
 */
static void php_imap_do_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
{
        char *mailbox, *user, *passwd;
        int mailbox_len, user_len, passwd_len;
        long retries = 0, flags = NIL, cl_flags = NIL;
        MAILSTREAM *imap_stream;
        pils *imap_le_struct;
        zval *params = NULL;
        int argc = ZEND_NUM_ARGS();

        if (zend_parse_parameters(argc, "pss|lla", &mailbox,
&mailbox_len, &user, &user_len,
                &passwd, &passwd_len, &flags, &retries, &params) ==
FAILURE) {
                return;
        }
        ...
        /* local filename, need to perform open_basedir check */
        if (mailbox[0] != '{' && php_check_open_basedir(mailbox)) {
                RETURN_FALSE;
        }

The actual segfault is on the access to mailbox[0] because mailbox is a
bogus pointer at this point and from userspace it is reproducable from
cli with just:

  sapi/cli/php -r 'imap_open("host", "user", "password");'

And here is where it gets mysterious. Looking at it with gdb,
zend_parse_parameters is setting that mailbox char* to 0x7fff00000000
while both the user and passwd ptrs are fine. BUT, if I recompile
ext/imap/php_imap.c using gcc -O3 the ptr is magically fine and no more
segfaults.

I suspected my gcc-4.8 on my Ubuntu laptop, so I built a completely
clean Debian 7.8.0 box which defaults to gcc-4.7.2 and I see the exact
same behaviour. segfaults under -O1/O2 but it is fine under -O0/O3. It
is also fine from the PHP 5.6 tree even though the changes are mostly
just removing TSRM and moving from zval** to zval* in a couple of places.

Things I have tried. changed it from "p" to "s" and also from "p" to "S"
and using a zend_string * instead. In both cases I got the same bogus
address back from zpp. Right now I am trying to make sense of the
generated assembly differences, but it is slow going.

Since almost the same code works for PHP 5.6 and this is limited to just
the imap extension, it seems more logical that something in the 5-6 to 7
changes is causing this and somehow -O3 optimizes its way around the
problem. So, does anyone see a mistake in these changes?

  https://gist.github.com/anonymous/b92dbb17172e9bff5247

-Rasmus

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to