Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

SplFixedArray: leak on re-initialisation during setSize(0), and setSize() broken on missing parent::__construct()

Fermée
#23,811 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
56/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
c, php
Domaine
backend, testing-qa

Piste de recherche

Start with spl_fixedarray_resize() and spl_fixedarray_dtor(), tracing how cached_resize is read during setSize(0), __construct(), __wakeup(), and __unserialize(). Use ext/spl/tests/bug62904.phpt as the existing regression-test entry point and add coverage for both re-entrant reinitialisation and a subclass that omits parent::__construct(). Done means the reported leaks and no-op resize are covered by tests and the expected sizes are returned.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

Bug Status: Needs Triage
Description

Two defects in SplFixedArray. Both come down to cached_resize being unreliable where it is read, and the fix touches the same function, so I am reporting them together.


1. Memory leak when the array is re-initialised from an element destructor during setSize(0)

spl_fixedarray_dtor() clears elements and size before running the element destructors (from the GH-11959 use-after-free fix), so the array then looks like one that was never constructed. __construct(), __wakeup() and __unserialize() gate on emptiness and re-initialise it, and the in-progress
clear discards the buffer they allocated.

The following code:

<?php
class Reentrant {
    public static ?SplFixedArray $arr = null;
    public function __destruct() {
        if (self::$arr !== null) {
            $arr = self::$arr;
            self::$arr = null;
            $arr->__construct(5);
        }
    }
}

$arr = new SplFixedArray(2);
Reentrant::$arr = $arr;
$arr[0] = new Reentrant();
$arr[1] = "tail";

$arr->setSize(0);
var_dump($arr->getSize());

Resulted in this output:

int(0)
ext/spl/spl_fixedarray.c(95) :  Freeing 0x0000e716d0e84070 (80 bytes)
=== Total 1 memory leaks detected ===

But I expected this output instead:

int(0)

Replacing __construct(5) with __unserialize(["a", "b", "c"]) or __wakeup() leaks the same way. A second site leaks when the destructor follows the re-init with a setSize(): the re-init resets the sentinel, so the setSize() performs a real nested shrink and its erealloc() buffer is discarded too.

This is the same bug as GH-21920, which cb3dc62fd90 fixed for a re-entrant setSize() by testing the resize sentinel first. The other three entry points were not covered.


2. setSize() silently does nothing on a subclass whose constructor does not call parent::__construct()

The following code:

<?php
class S extends SplFixedArray {
    public function __construct() {
    }
}

$s = new S();
var_dump($s->setSize(5));
var_dump($s->getSize());
$s[0] = 'x';

Resulted in this output:

bool(true)
int(0)

Fatal error: Uncaught OutOfBoundsException: Index invalid or out of range in /tmp/rep2.php:10
Stack trace:
#0 {main}
  thrown in /tmp/rep2.php on line 10

But I expected this output instead:

bool(true)
int(5)

zend_object_alloc() zeroes the object, so cached_resize starts at 0 instead of the documented -1. spl_fixedarray_resize() reads >= 0 as "a resize is already in progress" and returns early, so setSize() returns true and does nothing — permanently, for every call on that instance.

This is a regression: cb3dc62fd90 moved the "first initialization" branch below the sentinel check, which exposed the uninitialised sentinel. Before that, this path reached spl_fixedarray_init() and worked.

ext/spl/tests/bug62904.phpt already uses this class shape but only asserts "No crash" after a clone, which is why it was not caught.

PHP Version
PHP 8.4.27-dev (cli) (built from git, NTS DEBUG)
PHP 8.6.0-dev  (cli) (built from git, NTS DEBUG)
Operating System

Linux aarch64 (Ubuntu 24.04)

Langage dominant
C
Étoiles
40.4k
Forks
8.2k
Merge moyen
2 j 17 h
PR mergées (30 j)
115

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de php/php-src

Toutes les issues de php/php-src

Issues similaires

Plus d'issues C

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.