Bug #69371 [Asn->Csd]: Hash table collision leads to inaccessible array keys

From: Date: Sun, 05 Apr 2015 10:46:43 +0000
Subject: Bug #69371 [Asn->Csd]: Hash table collision leads to inaccessible array keys
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-191833@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=69371&edit=1

 ID:                 69371
 Updated by:         laruence@php.net
 Reported by:        berdir@php.net
 Summary:            Hash table collision leads to inaccessible array
                     keys
-Status:             Assigned
+Status:             Closed
 Type:               Bug
 Package:            Scripting Engine problem
 Operating System:   Linux
 PHP Version:        master-Git-2015-04-03 (Git)
 Assigned To:        dmitry
 Block user comment: N
 Private report:     N

 New Comment:

Automatic comment on behalf of laruence
Revision: http://git.php.net/?p=php-src.git;a=commit;h=b6aeab1b9177f4f6b89e7c1553fd946ea164002c
Log: Fixed bug #69371 (Hash table collision leads to inaccessible array keys)


Previous Comments:
------------------------------------------------------------------------
[2015-04-05 05:37:19] laruence@php.net

And a simple reproduce script is:

<?php
$array = array(
    "d6_node_type" => 1,
    "d6_filter_format" => 2,
    "d6_user" => 3,
    "d6_field_instance_widget_settings" => 4,
    "d6_field_formatter_settings" => 5,
);

$weights = array(
    5, 1, 3, 2, 0
);
array_multisort($weights, SORT_DESC, SORT_NUMERIC, $array);

var_dump($array["d6_node_type"]);

?>

thanks

------------------------------------------------------------------------
[2015-04-05 05:20:23] laruence@php.net

A quick fix attached:


diff --git a/ext/standard/array.c b/ext/standard/array.c
index 1ab9906..536771c 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -4538,6 +4538,8 @@ PHP_FUNCTION(array_multisort)
 		hash->nNextFreeElement = array_size;
 		if (repack) {
 			zend_hash_to_packed(hash);
+		} else {
+			zend_hash_rehash(hash);
 		}
 	}
 	HANDLE_UNBLOCK_INTERRUPTIONS();


thanks

------------------------------------------------------------------------
[2015-04-03 21:25:51] ircmaxell@php.net

I confirm this issue. On latest master the $migrations array does appear to become corrupted. I
haven't been able to narrow it down significantly.

------------------------------------------------------------------------
[2015-04-03 21:22:06] berdir@php.net

Description:
------------
We're working on making Drupal 8 compatible with PHP7.

A few of our tests are failing with very strange array related errors.

A lot of test that have a common base class and call the same method are failing with the same
problem. See https://www.drupal.org/node/2454439#comment-9788325.

Basically, there are two arrays, both are keyed with the same keys. We loop over one of them and
access the element in the second array. That results in a undefined index notice. But when comparing
with array_keys() or var_dump(), then the array key exists.

Changing the code to instead do a foreach and look for the matching key works fine:

-      $migration = $migrations[$migration_id];
+      foreach ($migrations as $id => $migration) {
+        // WTF PHP7, you drunk?
+        if ($id === $migration_id) {
+          break;
+        }
+      }

@ircmaxell has been debugging this and tracked it down to a hash collision between the array entries
d6_user and d6_node_type, which then results in d6_node_type not being accessible. For other tests,
it's other keys.

This only happens in this specific scenario, we haven't been able to reproduce it in a
standalone script.

To run the test, get the latest Drupal 8 (branch 8.0.x), and run the test like this:

php7 core/scripts/run-tests.sh --sqlite /tmp/test.sqlite --dburl sqlite://tmp/db.sqlite --class
"Drupal\migrate_drupal\Tests\d6\MigrateCckFieldRevisionTest"

Notes: that needs the curl and gd extensions, and it starts a second script to actually run the
test. To debug with gdb for example, you need something like this:

gdb --args '/usr/local/bin/php7' './core/scripts/run-tests.sh' --url
'' --sqlite '/tmp/test.sqlite' --dburl 'sqlite://tmp/db.sqlite' --php
'/usr/local/bin/php7' --test-id 1 --execute-test
'Drupal\migrate_drupal\Tests\d6\MigrateCckFieldRevisionTest'

(the first command needs to be run first, to set up the env, look for proc_open and print the
command to get he right now)



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=69371&edit=1


Thread (6 messages)

« previous php.bugs (#191833) next »