ArrayObject backing storage cycle causes unbounded recursion in spl_array_get_hash_table_ptr()

Aberta
#24,615 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
4/5
Tempo estimado
1-2 dias
Facilidade para iniciantes
51/100
Tipo de issue
Bug
Clareza
Razoavelmente clara
Status de atividade
Ativa
Stack de tecnologia
c, php
Domínio
backend, devtools

Direção de pesquisa

Start in ext/spl/spl_array.c, especially spl_array_set_array() and spl_array_get_hash_table_ptr(), and trace how SPL_ARRAY_USE_OTHER follows ArrayObject or ArrayIterator backing storage. Check existing SPL tests for exchangeArray() and constructor behavior, then add coverage showing that creating a multi-object backing cycle raises an error without recursion; verify ordinary backing objects still work.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

Description

ArrayObject::exchangeArray() (and the constructor) accept another ArrayObject as backing storage and only reject an object backing itself. Two objects that back each other are accepted silently, and the first operation that needs the storage recurses without limit in spl_array_get_hash_table_ptr() until the process crashes.

The following code:

<?php
$a = new ArrayObject([1]);
$b = new ArrayObject($a);   // $b uses $a's storage
$a->exchangeArray($b);      // $a now uses $b's storage: a cycle
echo "cycle built\n";
var_dump(count($a));

Resulted in this output (AddressSanitizer build):

==ERROR: AddressSanitizer: stack-overflow on address ...
    #0 spl_array_get_hash_table_ptr ext/spl/spl_array.c:65
    #1 spl_array_get_hash_table_ptr ext/spl/spl_array.c:71
    #2 spl_array_get_hash_table_ptr ext/spl/spl_array.c:71
    ...

But I expected this output instead: an error when the cycle is created (for example an InvalidArgumentException from exchangeArray()), as for other unsupported backing objects.

spl_array_set_array() sets SPL_ARRAY_USE_OTHER for any other ArrayObject/ArrayIterator and only special-cases Z_OBJ_P(object) == Z_OBJ_P(array); following the chain of SPL_ARRAY_USE_OTHER objects before accepting one would catch longer cycles too. Object backing storage is deprecated on master, but it is still accepted there.

Reproduced on 8.2.34-dev (512c04e39f) and 8.4.28-dev; the same code is on master.

This issue was found by an LLM-Enhanced Static Analysis Engine and verified manually.

PHP Version
PHP 8.4.28-dev, PHP 8.2.34-dev
Operating System

Linux (Ubuntu 20.04, x86_64)

Linguagem predominante
C
Estrelas
41.8k
Forks
8.5k
Merge médio
2d 13h
PRs com merge (30d)
145

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de php/php-src

Todas as issues de php/php-src

Issues semelhantes

Mais issues de C

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.