php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69371 Hash table collision leads to inaccessible array keys
Submitted: 2015-04-03 21:22 UTC Modified: 2015-04-05 05:37 UTC
Votes:2
Avg. Score:3.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:1 (50.0%)
From: berdir@php.net Assigned: dmitry (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: master-Git-2015-04-03 (Git) OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: berdir@php.net
New email:
PHP Version: OS:

 

 [2015-04-03 21:22 UTC] 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)


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-04-03 21:25 UTC] ircmaxell@php.net
-Package: Arrays related +Package: Scripting Engine problem
 [2015-04-03 21:25 UTC] 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:29 UTC] dmitry@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: dmitry
 [2015-04-05 05:20 UTC] 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-05 05:37 UTC] 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 10:46 UTC] laruence@php.net
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)
 [2015-04-05 10:46 UTC] laruence@php.net
-Status: Assigned +Status: Closed
 [2016-07-20 11:39 UTC] davey@php.net
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)
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sat Feb 01 18:01:29 2025 UTC