Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

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

Geschlossen
#23,811 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
56/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
c, php
Bereich
backend, testing-qa

Rechercherichtung

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.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

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)

Vorherrschende Sprache
C
Sterne
40.4k
Forks
8.2k
Ø Merge
2 T. 15 Std.
Gemergte PRs (30 T.)
113

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus php/php-src

Alle Issues in php/php-src

Ähnliche Issues

Weitere Issues zu C

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.