I wonder If I am completely missing the point, but the following piece
of code seems fishy to me:

ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint
nKeyLength, ulong h, int flag)
{
       uint nIndex;
       Bucket *p;

      ...

       while (p != NULL) {
               if ((p->h == h) && ((p->nKeyLength == 0) || /* Numeric
index */
                       ((p->nKeyLength == nKeyLength) &&
(!memcmp(p->arKey, arKey, nKeyLength))))) {
                       HANDLE_BLOCK_INTERRUPTIONS();
                        ...

If I am not completely mistaken this means: If this is a bucket with a
numeric index with the hash value of the key we want to delete, then
delete it, even when we wanted to delete a key with a string as index.

There's a fairly important bit in that first ...:
   if (flag == HASH_DEL_KEY) {
       h = zend_inline_hash_func(arKey, nKeyLength);
   }

When deleting a numeric index nKeyLength is passed as zero and h contains the numeric index so this if only matches when p->h == h and p->nKeyLength == 0 (indicating a numericly keyed bucket).

When deleting a string index, nKeyLength is non-zero and h as passed is unimportant since it's overridden with the actual hash of arKey and nKeyLength. The if then only evaluates true when the bucket hash matches the computed hash and the real key data in the bucket matches the real key data passed.

Yes, comparing p->h to h seems unnecessary since p->arKey is being compared to arKey anyway, but that seemingly redundant comparison saves a more costly memcmp() when the hashes differ.

-Sara
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to