# ZendEngine 2 - Double Free BUG

- Thread: https://externals.io/message/10241
- Original archive: https://news-web.php.net/php.internals/10241
- Started by Stefan Esser on 2004-06-02T11:43:09+00:00
- Messages: 6
- 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

---

## #10241 — Stefan Esser — 2004-06-02T11:43:09+00:00

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

Hi,

I ported Hardened-PHP to PHP5 yesterday night and got into the problem 
that there were some crashes. While one of the crashes is a problem in 
the port (at least I guess so), the other one was a detected double 
efree() in __set__get_001.phpt

I tracked this double free down to

static void zend_post_incdec_property(...)

where z is passed to

Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);

within this function z is freed and

                if (z->refcount == 0) {
                         zval_dtor(z);
                         FREE_ZVAL(z);
                 }

will free it again.

I fixed this by adding a z->refcount++ after
*retval = *z; but I do not know if this is the correct place,
because I am not really into ZE2 internals.

Stefan Esser

---

## #10242 — Stanislav Malyshev — 2004-06-02T11:54:21+00:00

URL: https://externals.io/message/10241#10242 · In reply to: #10241

SE>>Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
SE>>
SE>>within this function z is freed and

Why should write_property free z? 
-- 
Stanislav Malyshev, Zend Products Engineer   
stas@zend.com  http://www.zend.com/ +972-3-6139665 ext.115

---

## #10243 — Stefan Esser — 2004-06-02T12:24:20+00:00

URL: https://externals.io/message/10241#10243 · In reply to: #10242

Stanislav Malyshev wrote:
> SE>>Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
> SE>>
> SE>>within this function z is freed and
> 
> Why should write_property free z? 

static int zend_std_call_setter(zval *object, zval *member, zval *value 
TSRMLS_DC)
{
         zval **call_args[2];
         zval *retval = NULL;
         zval __set_name;
         int call_result;
         int ret;

         /* __set handler is called with two arguments:
            property name
            value to be set

            it should return whether the call was successfull or not
         */
         INIT_PZVAL(&__set_name);
         ZVAL_STRINGL(&__set_name, ZEND_SET_FUNC_NAME, 
sizeof(ZEND_SET_FUNC_NAME)-1, 0);

         call_args[0] = &member;
         value->refcount++;
         call_args[1] = &value;

         /* go call the __set handler */
         call_result = call_user_function_ex(NULL,
 
          &object,
 
          &__set_name,
 
          &retval,
 
          2, call_args,
 
          0, `NULL` TSRMLS_CC);

         /*
            call_result is if call_user_function gone OK.
            retval shows if __get method went OK.
         */


         if (call_result == FAILURE) {
                 zend_error(E_ERROR, "Could not call __set handler for 
class %s", Z_OBJCE_P(object)->name);
                 return FAILURE;
         }

         zval_ptr_dtor(&value);


Maybe you should ask the person who wrote it "why". Well the problem is 
not that it frees it. The problem is that the refcount is zero when the
std_setter is called.

Stefan

---

## #10244 — Stanislav Malyshev — 2004-06-02T12:46:22+00:00

URL: https://externals.io/message/10241#10244 · In reply to: #10243

SE>>Maybe you should ask the person who wrote it "why". Well the problem
SE>>is not that it frees it. The problem is that the refcount is zero when
SE>>the std_setter is called.

I think you are right, it should be fixed in zend_post_incdec_property. Do 
you have reproducing code example so it can be tested? 
-- 
Stanislav Malyshev, Zend Products Engineer   
stas@zend.com  http://www.zend.com/ +972-3-6139665 ext.115

---

## #10246 — Stefan Esser — 2004-06-02T12:59:49+00:00

URL: https://externals.io/message/10241#10246 · In reply to: #10244

Stanislav Malyshev wrote:

> I think you are right, it should be fixed in zend_post_incdec_property. Do 
> you have reproducing code example so it can be tested? 

No it cannot be tested. In the default configuration Zend_MM is 
activated. This will catch double frees. No violation will happen when 
it is activated. This is why valgrind etc... do not catch it.

And I think there is another bug with simple classes on termination
of a request.

class xy
{
	function a()
	{
	}
}

$y = new xy();

crashes over here with Hardened-PHP applied AND maintainer-zts 
activated. It crashs in a llist destruction from within
zend_deactivate. The reason for the crash seems that the memory
pointed to by TRMS_ls is already freed.

Stefan

---

## #10266 — Marcus Boerger — 2004-06-03T19:21:47+00:00

URL: https://externals.io/message/10241#10266 · In reply to: #10246

Hello Stefan,

i made a fix for TSRM which is comitted but disabled by
#if MBO_0
could you add
#define MBO_0
at the to of TSRM/TSRM.c and check if that helps a bit?

marcus

Wednesday, June 2, 2004, 2:59:49 PM, you wrote:

> Stanislav Malyshev wrote:

> > […]

> No it cannot be tested. In the default configuration Zend_MM is 
> activated. This will catch double frees. No violation will happen when 
> it is activated. This is why valgrind etc... do not catch it.

> And I think there is another bug with simple classes on termination
> of a request.

> class xy
> {
> 	function a()
> 	{
> 	}
> }

> $y = new xy();

> crashes over here with Hardened-PHP applied AND maintainer-zts 
> activated. It crashs in a llist destruction from within
> zend_deactivate. The reason for the crash seems that the memory
> pointed to by TRMS_ls is already freed.

> Stefan




-- 
Best regards,
 Marcus                            mailto:helly@php.net
