Skip to content

Undefined Array Key with a Key as a Long String #13279

Closed

Description

@designextreme

Description

The following code:

<?php
class array_test
{
	public $array = array();

	public function __construct()
	{
		$this->array = array(
			'1696007099_5_d386ca263816163166823ef00979d944' => array(
				'order' => 1
			),
			'1663066269_5_8c82ae69264d73f7ae7ce3a619501231' => array(
				'order' => 0
			)
		);

		uksort($this->array, function ($a, $b)
			{
				return $this->array[$a]['order'] - $this->array[$b]['order'];
			}
		);
	}
}

new array_test;

Resulted in this output:

Warning:  Undefined array key "1696007099_5_d386ca263816163166823ef00979d944" in .../array_test.php on line 19

But I expected this output instead:

No warnings/errors, just a freshly sorted array.

I have tested the following:

echo $a; // 1696007099_5_d386ca263816163166823ef00979d944
echo $b; // 1663066269_5_8c82ae69264d73f7ae7ce3a619501231
echo array_key_exists($a, $this->array); // FALSE
echo isset($this->array[$a]); // FALSE
echo array_key_first($this->array); // 1696007099_5_d386ca263816163166823ef00979d944
echo array_keys($this->array)[0]; // 1696007099_5_d386ca263816163166823ef00979d944

PHP Version

PHP 8.3

Operating System

CentOS 7.9

Activity

  1. iluuu1994 commented on Jan 30, 2024

    @iluuu1994
    Member

    I don't see this warning. How are you running this code? Just in a CLI script?

  2. designextreme commented on Jan 30, 2024

    @designextreme
    Author

    I've attempted to simplify the PHP contained within a large script and may have failed in the process. I think I missed something with the array...

  3. designextreme commented on Jan 30, 2024

    @designextreme
    Author

    The example code is a simplified version of a WordPress plugin. It's really odd how array values can't be accessed by the keys here, yet they do exist. It is covered in a forum post at: WordPress.org. This is only in PHP 8.3, not 8.2,

    In the meantime, I will try to create a simple version so you can replicate it.

  4. SVGAnimate commented on Jan 30, 2024

    @SVGAnimate
    Contributor

    The mbstring extension has changed. I bet that's it.

  5. designextreme commented on Jan 30, 2024

    @designextreme
    Author

    @SVGAnimate I think you're on to something. The actual array does contain emoticons and more besides. I am still attempting to create the "simple" version using the review data from the WordPress plugin.

  6. 6 remaining items

  7. iluuu1994 commented on Jan 31, 2024

    @iluuu1994
    Member

    It is iterating through an array with keys that don't "exist". Even if the fault occurred before in the code, how is this possible?

    I think this would be possible if the string is placed in the wrong bucket, i.e. if it was originally saved in one bucket and then the string+hash change. I suppose this could happen if there was a refcounting bug where the string is modified in-place.

    But let's wait for your reproducer.

  8. designextreme commented on Jan 31, 2024

    @designextreme
    Author

    Got it! Here is the simplified example:

    <?php
    
    class array_test
    {
    	public $array = array();
    
    	public function __construct()
    	{
    		$this->array = array(
    			'1696007099_5_d386ca263816163166823ef00979d944' => array(
    				'id' => 1,
    				'order' => 1
    			),
    			'1663066269_5_8c82ae69264d73f7ae7ce3a619501231' => array(
    				'id' => 2,
    				'order' => 0
    			)
    		);
    
            $relevance = 0;
            $checked_ids = array();
    
            foreach (array_keys($this->array) as $key)
            {
                $a = $this->array[$key];
                
                if (!in_array($a['id'], $checked_ids, TRUE))
                {
    				/* 
    					This part introduces the key error
     				*/
                    $this->array[$key]['removable'] = TRUE;
                    $this->array[$key]['order'] = $relevance;
                    $relevance++;
                }
            }
    
    		uksort($this->array, function ($a, $b)
    			{
    				/*
    					A warning is produced:
    					Undefined array key "1696007099_5_d386ca263816163166823ef00979d944" in array_test.php on line 44
    				*/
    				return $this->array[$a]['order'] - $this->array[$b]['order'];
    			}
    		);
    
            echo '<pre>' . print_r($this->array, TRUE) . '</pre>';
    	}
    }
    
    new array_test;
    

    I did try this with some multi-byte characters and emoticons, but this didn't affect the outcome.

  9. SVGAnimate commented on Jan 31, 2024

    @SVGAnimate
    Contributor

    On PHP 8.3.1 i do not have Notice/Warning

  10. iluuu1994 commented on Jan 31, 2024

    @iluuu1994
    Member

    Hmm yes. This is caused by #11060. The issue is that during the user call, the array is essentially unstable. I think this should be reverted for php_usort. /cc @nielsdos (I'm creating a PR)

  11. designextreme commented on Jan 31, 2024

    @designextreme
    Author

    With PHP 8.3.2, here are the log entries:

    [31-Jan-2024 12:13:58 UTC] PHP Warning:  Undefined array key "1696007099_5_d386ca263816163166823ef00979d944" in array_test.php on line 44
    [31-Jan-2024 12:13:58 UTC] PHP Warning:  Trying to access array offset on null in array_test.php on line 44
    [31-Jan-2024 12:13:58 UTC] PHP Warning:  Undefined array key "1663066269_5_8c82ae69264d73f7ae7ce3a619501231" in array_test.php on line 44
    [31-Jan-2024 12:13:58 UTC] PHP Warning:  Trying to access array offset on null in array_test.php on line 44
    
  12. added 2 commits that reference this issue on Jan 31, 2024
    d475484
    d65c395
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions