# memory_limit und Out-of-Memory: Was im Inneren passiert

> PHP Out of Memory verständlich erklärt: wie memory_limit zählt, was beim Abbruch intern geschieht und was das für CVE-2026-109618 und Ihre Server heißt.

Quelle: https://phpsos.de/php/out-of-memory/  
Stand: 25.10.2026  
Anbieter: PHP SOS, PHP-Notfallhilfe und Server-Sicherheit. Soforthilfe per WhatsApp: https://wa.me/491736494914?text=Hallo%20PHP%20SOS%2C%20wir%20brauchen%20Hilfe%20mit%20unserem%20PHP-Server.%20Firma%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kurz gesagt:** Ein PHP-Out-of-Memory-Fehler entsteht, wenn ein Skript mehr Speicher anfordern will, als die Einstellung `memory_limit` erlaubt (Standard: 128 MB je Anfrage). PHP bricht die Anfrage dann mit einem fatalen Fehler ab und räumt auf. Genau dieser Abbruch- und Aufräumweg war bei CVE-2026-109618, einer der beiden PHP2Shell-Lücken, fehlerhaft. Seit PHP 8.5.12, 8.4.27, 8.3.36 und 8.2.35 ist `memory_limit` eine weiche Grenze, ergänzt um die harte Grenze `memory_hard_limit_percent`.

## Was bedeutet „Allowed memory size exhausted“?

Die bekannte Fehlermeldung lautet sinngemäß: „Allowed memory size of 134217728 bytes exhausted (tried to allocate …)“. Die erste Zahl ist das eingestellte Limit in Bytes, hier 128 MB. Ein Skript hat also versucht, Speicher über diese Grenze hinaus zu belegen, etwa beim Laden einer großen Datei, einer riesigen Datenbankabfrage oder durch eine Endlosschleife.

Für Entscheider wichtig: Die Grenze gilt je PHP-Prozess und je Anfrage, nicht für den ganzen Server. Sie schützt den Server davor, dass ein einzelnes fehlerhaftes Skript allen Speicher aufbraucht. Die Gesamtlast ergibt sich erst aus der Zahl der gleichzeitig laufenden Worker. Bei 20 PHP-FPM-Workern mit je 256 MB Grenze sind das rechnerisch über 5 GB.

## Wie PHP Speicher zählt

PHP verwaltet Speicher für Anfragen über einen eigenen Speichermanager, den Zend Memory Manager. Er holt größere Blöcke vom Betriebssystem und verteilt sie intern an Variablen, Arrays und Objekte. Gegen diesen reservierten Wert prüft PHP das `memory_limit`. Speicher, den eine Erweiterung direkt beim Betriebssystem anfordert, taucht laut Handbuch in dieser Zählung nicht auf.

Sie können die Werte im Code sichtbar machen:

```php
<?php
echo memory_get_usage(), PHP_EOL;       // aktuell vom Skript belegter Speicher
echo memory_get_usage(true), PHP_EOL;   // vom Speichermanager reserviert; dagegen prüft memory_limit
$liste = range(1, 200000);
echo memory_get_peak_usage(), PHP_EOL;  // bisheriger Spitzenwert
unset($liste);
memory_reset_peak_usage();              // Spitzenwert zurücksetzen, ab PHP 8.2
```

Wie Referenzzählung und Garbage Collection den Speicher wieder freigeben, erklärt die Seite [Speicherverwaltung in PHP](https://phpsos.de/php/speicherverwaltung/).

## Was beim Out-of-Memory im Inneren passiert

Vereinfacht läuft ein Speicherabbruch in diesen Schritten ab:

1. Das Skript fordert Speicher an, zum Beispiel für ein neues Array-Element oder beim Einlesen von Anfragedaten.
2. Der Speichermanager prüft, ob die Anforderung die Grenze überschreitet.
3. Ist das der Fall, löst PHP einen fatalen Fehler aus und verlässt die laufende Verarbeitung sofort, auch mitten in einer halb erledigten Aufgabe.
4. Registrierte Shutdown-Funktionen laufen noch; damit protokollieren viele Anwendungen den Fehler.
5. Am Ende räumt PHP die Anfrage auf und gibt deren Speicher frei. Der Worker steht danach für die nächste Anfrage bereit.

Der heikle Punkt ist Schritt 5. Das Aufräumen muss mit Datenstrukturen umgehen können, die beim Abbruch erst halb angelegt waren. Ein gewöhnlicher Speicherabbruch gilt laut Sicherheitsrichtlinie des PHP-Projekts nicht als Sicherheitslücke, solange das Limit die Anforderung ablehnt und nur die aktuelle Anfrage endet. Bei CVE-2026-109618 war genau diese Annahme verletzt: Laut php.net konnte der Out-of-Memory-Zustand PHP unterbrechen, während interne Anfragedaten nur teilweise initialisiert waren, und das Aufräumen behandelte ungültige Daten dann als gültig. Details zur Ausnutzung veröffentlichen wir nicht; die Einordnung der Lücke steht unter [CVE-2026-109618](https://phpsos.de/php2shell/cve-2026-109618/).

## Die neue weiche und harte Speichergrenze

Mit den Sicherheitsreleases vom 21.10.2026 hat das PHP-Projekt das Verhalten geändert. Laut Handbuch ist `memory_limit` seitdem eine weiche Grenze: Eine Anforderung, die sie überschreitet, darf in den meisten Fällen noch abgeschlossen werden, bevor der fatale Fehler folgt. Eine separate harte Grenze begrenzt, wie weit das gehen darf.

| Direktive | Standard | Änderbar | Bedeutung |
|---|---|---|---|
| `memory_limit` | 128M | INI_ALL | Speichergrenze je Anfrage, `-1` = keine Grenze |
| `memory_hard_limit_percent` | nicht gesetzt | INI_ALL | Harte Grenze in Prozent von `memory_limit`, neu seit 8.5.12, 8.4.27, 8.3.36, 8.2.35 |
| `post_max_size` | 8M | INI_PERDIR | Maximale Größe der POST-Daten |
| `upload_max_filesize` | 2M | INI_PERDIR | Maximale Größe einer hochgeladenen Datei |

Ein Beispiel aus dem Handbuch: Bei `memory_limit=128M` und `memory_hard_limit_percent=150` liegt die harte Grenze bei 192 MB. Das Handbuch nennt die Direktive zugleich als Erkennungsmerkmal: Kennt eine PHP-Version sie nicht, ist sie von CVE-2026-109618 und CVE-2026-109619 betroffen. Ein schneller Test für jede installierte PHP-Version:

```bash
php -r 'var_dump(ini_get("memory_hard_limit_percent"));'
# bool(false) bedeutet: Direktive unbekannt
```

Bei Paketen aus Distributionen mit Backport bleibt der Paket-Changelog der maßgebliche Nachweis, wie unter [PHP-Version und Patchstand richtig prüfen](https://phpsos.de/php2shell/php-version-pruefen/) beschrieben. Prüfen Sie außerdem die PHP-FPM-Binary separat, denn sie kann eine andere Version haben als die Kommandozeile.

## Speichergrenzen und PHP2Shell: Was Admins jetzt beachten

Die Übergangsmaßnahmen von php.net zu CVE-2026-109618 drehen sich fast alle um Speicher und Anfragegrößen. Sie verringern das Risiko, ersetzen aber das Update nicht:

```ini
; FPM-Pool, z. B. /etc/php/8.3/fpm/pool.d/www.conf
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M        ; 32M, wenn Uploads nötig sind
php_admin_value[upload_max_filesize] = 6M  ; unter post_max_size halten
```

Drei Punkte sind dabei entscheidend. Erstens darf keine Anwendung, kein Verzeichnis und kein anderer Pool wieder eine endliche Grenze setzen; php.net verlangt ausdrücklich diese Kontrolle. Zweitens braucht ein Dienst mit `memory_limit=-1` eine Grenze von außen, über Container oder cgroup, nach php.net am besten so, dass nur der betroffene Worker beendet wird. `RLIMIT_AS` und `RLIMIT_DATA` sind laut php.net ungeeignet. Drittens empfiehlt php.net Grenzen am Webserver oder Proxy für Anfragegröße, Zahl der Felder, Multipart-Teile, Header und Verschachtelungstiefe.

> **Wichtig:**
> `memory_limit=-1` ohne Speichergrenze von außen kann einen Server bei hoher Last komplett lahmlegen. Setzen Sie die Übergangsmaßnahmen nur als Paket und nur bis zum Update.

Wie Sie die Grenze mit systemd setzen, steht unter [Speichergrenzen mit systemd und cgroups](https://phpsos.de/blog/speichergrenzen-systemd-cgroups/); die Dauerlösung für den Alltag beschreibt [memory_limit richtig setzen](https://phpsos.de/blog/memory-limit-richtig-setzen/).

## Wie hilft PHP SOS konkret?

Über den [PHP-Patch-Service](https://phpsos.de/leistungen/php-patch-service/) gehen wir so vor:

- **Bestand prüfen:** Wir erfassen jede PHP-Version auf dem Server, getrennt nach CLI, FPM und Apache-Modul, und testen, ob die Fix-Version läuft.
- **Speichergrenzen ordnen:** Wir prüfen, wo `memory_limit` überall gesetzt wird, und richten Pool- und Systemgrenzen so ein, dass sie zusammenpassen.
- **Übergang absichern:** Wo das Update noch blockiert ist, setzen wir die Maßnahmen von php.net vollständig und gegen Überschreiben gesperrt.
- **Nachweis liefern:** Sie erhalten Versionen, Paketstände und Konfiguration vor und nach dem Eingriff schriftlich.


## Häufige Fragen

**Was bedeutet die Meldung „Allowed memory size exhausted“?**  
Ein Skript wollte mehr Speicher anfordern, als memory_limit erlaubt. PHP bricht die laufende Anfrage dann mit einem fatalen Fehler ab. Andere Anfragen und der Server selbst laufen weiter.

**Gilt memory_limit für den ganzen Server?**  
Nein, die Grenze gilt je PHP-Prozess und Anfrage. Laufen 20 FPM-Worker mit je 256 MB Grenze, können sie zusammen theoretisch über 5 GB belegen. Die Gesamtgrenze muss deshalb über Pool-Größe, systemd oder Container gesetzt werden.

**Was ist memory_hard_limit_percent?**  
Eine neue Direktive, die mit PHP 8.5.12, 8.4.27, 8.3.36 und 8.2.35 kam. Sie setzt eine harte Grenze als Prozentwert von memory_limit, die nie überschritten wird. memory_limit selbst ist seitdem eine weiche Grenze.

**Schützt memory_limit=-1 vor PHP2Shell?**  
Nur teilweise. php.net nennt die Einstellung als Übergangsmaßnahme gegen CVE-2026-109618, ausdrücklich ohne vollständigen Schutz. Sie braucht zwingend eine Speichergrenze von außen, und das Update bleibt Pflicht.

## Quellen

- [PHP-Handbuch: Core-Einstellungen (memory_limit, memory_hard_limit_percent)](https://www.php.net/manual/en/ini.core.php)
- [PHP-Handbuch: memory_get_usage()](https://www.php.net/manual/en/function.memory-get-usage.php)
- [php.net: Sicherheitsmeldungen vom 21.10.2026](https://www.php.net/)
