# ZE2 broken by newer gcc

- Thread: https://externals.io/message/55362
- Original archive: https://news-web.php.net/php.internals/55362
- Started by Flavius Aspra on 2011-09-11T10:27:02+00:00
- Messages: 4
- 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

---

## #55362 — Flavius Aspra — 2011-09-11T10:27:02+00:00

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

Hi

I think I've found a bug in the engine, and I think it occures only with 
the latest gcc ("gcc version 4.6.1 20110819 (prerelease)"), since it 
used to work with earlier versions.

For example line 867 
http://lxr.php.net/opengrok/xref/PHP_5_3/Zend/zend_execute_API.c#867 
should be

     && PZVAL_IS_REF((*fci->params)[i])) {

that's what has worked for me at least. Otherwise it ends with a segfault.

It may also be gcc breaking BC. So I'm not sure whose "fault" it is, but 
I think [] takes precedence over * in the C specification.

Could someone please verify this issue?

Regards,
Flavius
-- 
What I cannot create, I do not understand. -- Feynman

---

## #55369 — keisial@gmail.com — 2011-09-11T21:10:23+00:00

URL: https://externals.io/message/55362#55369 · In reply to: #55362

Flavius Aspra wrote:
> Hi
>
> I think I've found a bug in the engine, and I think it occures only 
> with the latest gcc ("gcc version 4.6.1 20110819 (prerelease)"), since 
> it used to work with earlier versions.
>
> For example line 867 
> http://lxr.php.net/opengrok/xref/PHP_5_3/Zend/zend_execute_API.c#867 
> should be
>
> && PZVAL_IS_REF((*fci->params)[i])) {
>
> that's what has worked for me at least. Otherwise it ends with a 
> segfault.
>
> It may also be gcc breaking BC. So I'm not sure whose "fault" it is, 
> but I think [] takes precedence over * in the C specification.
>
> Could someone please verify this issue?
>
> Regards,
> Flavius
[] does take precedence over *
In this case the macro expansion would also be relevant, but it looks 
like it would end up as a simple zval_isref_p 
<http://lxr.php.net/opengrok/s?refs=zval_isref_p&project=PHP_5_3>((*fci->params)[i]);

---

## #55379 — Dmitry Stogov — 2011-09-12T06:45:06+00:00

URL: https://externals.io/message/55362#55379 · In reply to: #55362

Hi Flavius,

Unfortunately, the proposed fix is wrong.
It changes the operators precedence and it's definitely wrong.
I suppose the crash caused by side effect of some other bug.

Try to run the same script with valgrind.

Thanks. Dmitry.



> Hi
>
> I think I've found a bug in the engine, and I think it occures only with
> the latest gcc ("gcc version 4.6.1 20110819 (prerelease)"), since it
> used to work with earlier versions.
>
> For example line 867
> http://lxr.php.net/opengrok/xref/PHP_5_3/Zend/zend_execute_API.c#867
> should be
>
> && PZVAL_IS_REF((*fci->params)[i])) {
>
> that's what has worked for me at least. Otherwise it ends with a segfault.
>
> It may also be gcc breaking BC. So I'm not sure whose "fault" it is, but
> I think [] takes precedence over * in the C specification.
>
> Could someone please verify this issue?
>
> Regards,
> Flavius

---

## #55384 — Flavius Aspra — 2011-09-12T12:32:47+00:00

URL: https://externals.io/message/55362#55384 · In reply to: #55379

> Hi Flavius,
>
> Unfortunately, the proposed fix is wrong.
> It changes the operators precedence and it's definitely wrong.
> I suppose the crash caused by side effect of some other bug.
>
> Try to run the same script with valgrind.
>
> Thanks. Dmitry.
>
>


Please test the following POC with gcc 4.6.1 on x64 first (perhaps 
slightly earlier versions behave the same, but this one is for sure), 
the dump_container() function simulates what the ZE does in 
zend_call_function() and many other places. You can also look at what 
valgrind says too and compare. I haven't dwelt on it at the ASM level, 
but certainly something has changed. My bet is that GCC has had wrong 
the operator precedence, and now they've fixed it.

I'm not speaking from my imagination, I'm speaking from what I've seen 
and what I've tested, in practice. No theory. In the "meta" extension I 
am calling zend_call_function(), which is how I've discovered this. The 
POC resembles what is happenning as close as possible.


#include <stdio.h>
#include <stdlib.h>

#define NUMS 10

/* a "zval" */
typedef struct _foo {
     char *t;
     int i;
} foo;

/* a "zend_fcall_info" */
typedef struct _foo_container {
     foo ***foos;
} container;

foo** init_foos(void) {
     foo** f, *f2;
     int i;
     f = malloc(sizeof(foo*)*NUMS);
     for(i=0; i < NUMS; i++) {
         f2 = malloc(sizeof(foo));
         printf("allocated %p ", f2);
         f[i] = f2;
         f[i]->i = i*11+1;
         printf("with value %d\n", i*11+1);
     }
     return f;
}

void dump_container(container *c) {
     int i;
     for(i=0; i < NUMS; i++) {
         //working:
         printf("foo[%d]=%d at %p\n", i, (*c->foos)[i]->i, (*c->foos)[i]);
         //similar to ZE, crashing (not at i=0, but on my machine at i=1 
it already delivers garbage, at i=2 it finnaly crashes
         //if you're lucky, increase NUMS at the top
         printf("foo[%d]=%d at %p\n", i, (*c->foos)[i]->i, *c->foos[i]);
     }
}

int main(void) {
     container c;
     foo **foos;

     foos = init_foos();

     c.foos = &foos;
     int i;
     for(i=0; i < NUMS; i++) {
         printf("%d %d at %p\n", i, foos[i]->i, foos[i]);
     }
     printf("------------------\n");
     dump_container(&c);
     free(foos);
     return EXIT_SUCCESS;
}



-- 
What I cannot create, I do not understand. -- Feynman
