# Question about zend_hash.c, UPDATE_DATA macro

- Thread: https://externals.io/message/3628
- Original archive: https://news-web.php.net/php.internals/3628
- Started by Vesselin Atanasov on 2003-07-29T11:50:16+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

---

## #3628 — Vesselin Atanasov — 2003-07-29T11:50:16+00:00

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

Hello.
In PHP5, file zend_hash.c there is a macro

#define UPDATE_DATA(ht, p, pData, nDataSize)
\
        if (nDataSize == sizeof(void*))
{
\
                if (!(p)->pDataPtr)
{
\
                        pefree((p)->pData, (ht)->persistent);
\
                }
\
                memcpy(&(p)->pDataPtr, pData, sizeof(void *));
\
                (p)->pData = &(p)->pDataPtr;
\
        } else
{
\
                if ((p)->pDataPtr)
{
\
                        (p)->pData = (void *) pemalloc(nDataSize,
(ht)->persistent);    \
                        (p)->pDataPtr=NULL;
\
                }
\
                memcpy((p)->pData, pData, nDataSize);
\
        }

The macro is used to update a hash table element in
zend_hash_add_or_update(). But it seems to me that if p->pData already
points to a
data block that hash size != sizeof (void *), and the macro is called to
update the hash element with another block that has
size != sizeof (void *), then the data block pointed at by p->pData will not
be reallocated and the last memcpy() call will overwrite the old
data block with the new data. This could possibly lead to memory corruption
if the new block is bigger than the old block.

Could any of the PHP developers comment on this?

---

## #3630 — Wez Furlong — 2003-07-29T11:57:34+00:00

URL: https://externals.io/message/3628#3630 · In reply to: #3628

I think I brought this up here before too.
I can't remember the outcome - would you mind looking through the archives?

--Wez.

> The macro is used to update a hash table element in
> zend_hash_add_or_update(). But it seems to me that if p->pData already
> points to a
> data block that hash size != sizeof (void *), and the macro is called to
> update the hash element with another block that has
> size != sizeof (void *), then the data block pointed at by p->pData will
not
> be reallocated and the last memcpy() call will overwrite the old
> data block with the new data. This could possibly lead to memory
corruption
> if the new block is bigger than the old block.
>
> Could any of the PHP developers comment on this?

---

## #3635 — Andi Gutmans — 2003-07-29T16:11:47+00:00

URL: https://externals.io/message/3628#3635 · In reply to: #3628

Just to make sure I understand what you're asking, are your first and 
second updates of data with different sizes?

Andi

At 02:50 PM 7/29/2003 +0300, Vesselin Atanasov wrote:
>Hello.
>In PHP5, file zend_hash.c there is a macro
>
>#define UPDATE_DATA(ht, p, pData, nDataSize)
>\
>         if (nDataSize == sizeof(void*))
>{
>\
>                 if (!(p)->pDataPtr)
>{
>\
>                         pefree((p)->pData, (ht)->persistent);
>\
>                 }
>\
>                 memcpy(&(p)->pDataPtr, pData, sizeof(void *));
>\
>                 (p)->pData = &(p)->pDataPtr;
>\
>         } else
>{
>\
>                 if ((p)->pDataPtr)
>{
>\
>                         (p)->pData = (void *) pemalloc(nDataSize,
>(ht)->persistent);    \
>                         (p)->pDataPtr=NULL;
>\
>                 }
>\
>                 memcpy((p)->pData, pData, nDataSize);
>\
>         }
>
>The macro is used to update a hash table element in
>zend_hash_add_or_update(). But it seems to me that if p->pData already
>points to a
>data block that hash size != sizeof (void *), and the macro is called to
>update the hash element with another block that has
>size != sizeof (void *), then the data block pointed at by p->pData will not
>be reallocated and the last memcpy() call will overwrite the old
>data block with the new data. This could possibly lead to memory corruption
>if the new block is bigger than the old block.
>
>Could any of the PHP developers comment on this?

---

## #3648 — Andi Gutmans — 2003-07-30T19:02:06+00:00

URL: https://externals.io/message/3628#3648 · In reply to: #3628

Yes you are right. There indeed seems to be some flaw in the logic. I'll 
commit a fix in a few minutes.
Please test it and let me know if it fixes your problems.

Thanks,

Andi


At 02:50 PM 7/29/2003 +0300, Vesselin Atanasov wrote:
>Hello.
>In PHP5, file zend_hash.c there is a macro
>
>#define UPDATE_DATA(ht, p, pData, nDataSize)
>\
>         if (nDataSize == sizeof(void*))
>{
>\
>                 if (!(p)->pDataPtr)
>{
>\
>                         pefree((p)->pData, (ht)->persistent);
>\
>                 }
>\
>                 memcpy(&(p)->pDataPtr, pData, sizeof(void *));
>\
>                 (p)->pData = &(p)->pDataPtr;
>\
>         } else
>{
>\
>                 if ((p)->pDataPtr)
>{
>\
>                         (p)->pData = (void *) pemalloc(nDataSize,
>(ht)->persistent);    \
>                         (p)->pDataPtr=NULL;
>\
>                 }
>\
>                 memcpy((p)->pData, pData, nDataSize);
>\
>         }
>
>The macro is used to update a hash table element in
>zend_hash_add_or_update(). But it seems to me that if p->pData already
>points to a
>data block that hash size != sizeof (void *), and the macro is called to
>update the hash element with another block that has
>size != sizeof (void *), then the data block pointed at by p->pData will not
>be reallocated and the last memcpy() call will overwrite the old
>data block with the new data. This could possibly lead to memory corruption
>if the new block is bigger than the old block.
>
>Could any of the PHP developers comment on this?
