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
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
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-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 11:01:29 2024 UTC