Röviden: A PHP Out-of-Memory hiba akkor keletkezik, ha egy szkript több memóriát akar lefoglalni, mint amennyit a memory_limit beállítás megenged (alapértelmezés: 128 MB kérésenként). A PHP ilyenkor végzetes hibával megszakítja a kérést, és rendet tesz. Éppen ez a megszakítási és takarítási út volt hibás a CVE-2026-109618-nál, a két PHP2Shell-rés egyikénél. A PHP 8.5.12, 8.4.27, 8.3.36 és 8.2.35 óta a memory_limit puha határ, amelyet a memory_hard_limit_percent kemény határ egészít ki.
Mit jelent az „Allowed memory size exhausted”?
Az ismert hibaüzenet értelemszerűen így szól: „Allowed memory size of 134217728 bytes exhausted (tried to allocate …)”. Az első szám a beállított korlát bájtban, itt 128 MB. Egy szkript tehát megpróbált ezen a határon túl memóriát lefoglalni, például egy nagy fájl betöltésekor, egy hatalmas adatbázis-lekérdezésnél vagy egy végtelen ciklus miatt.
A döntéshozók számára fontos: a határ PHP-folyamatonként és kérésenként érvényes, nem az egész szerverre. Megvédi a szervert attól, hogy egyetlen hibás szkript az összes memóriát felhasználja. Az összterhelés csak az egyidejűleg futó workerek számából adódik. 20 PHP-FPM-workernél, egyenként 256 MB határral ez számítás szerint több mint 5 GB.
Hogyan számolja a PHP a memóriát
A PHP a kérések memóriáját saját memóriakezelőn, a Zend Memory Manageren keresztül kezeli. Nagyobb blokkokat kér az operációs rendszertől, és belsőleg osztja szét őket a változók, tömbök és objektumok között. A PHP a memory_limit-et ezzel a lefoglalt értékkel szemben ellenőrzi. Az a memória, amelyet egy bővítmény közvetlenül az operációs rendszertől kér, a kézikönyv szerint nem jelenik meg ebben a számításban.
Az értékeket a kódban láthatóvá teheti:
<?php
echo memory_get_usage(), PHP_EOL; // a szkript által jelenleg lefoglalt memória
echo memory_get_usage(true), PHP_EOL; // a memóriakezelő által lefoglalt; a memory_limit ezt ellenőrzi
$liste = range(1, 200000);
echo memory_get_peak_usage(), PHP_EOL; // az eddigi csúcsérték
unset($liste);
memory_reset_peak_usage(); // csúcsérték visszaállítása, a PHP 8.2-től
Hogyan szabadítja fel ismét a memóriát a referenciaszámlálás és a szemétgyűjtés, azt a Memóriakezelés a PHP-ban oldal magyarázza.
Mi történik belül Out-of-Memory esetén
Egyszerűsítve a memória miatti megszakítás ezekben a lépésekben zajlik:
- A szkript memóriát kér, például egy új tömbelemhez vagy kéradatok beolvasásakor.
- A memóriakezelő ellenőrzi, hogy a kérés túllépi-e a határt.
- Ha igen, a PHP végzetes hibát vált ki, és azonnal elhagyja a folyamatban lévő feldolgozást, akár egy félig elvégzett feladat közepén is.
- A regisztrált shutdown-függvények még lefutnak; sok alkalmazás ezekkel naplózza a hibát.
- A végén a PHP rendet tesz a kérésnél, és felszabadítja a memóriáját. A worker ezután a következő kérésre készen áll.
A kényes pont az 5. lépés. A takarításnak olyan adatszerkezetekkel is meg kell birkóznia, amelyek a megszakításkor még csak félig voltak létrehozva. A PHP-projekt biztonsági irányelve szerint egy szokásos memória miatti megszakítás nem biztonsági rés, amíg a limit elutasítja a kérést, és csak az aktuális kérés ér véget. A CVE-2026-109618-nál éppen ez a feltevés sérült: a php.net szerint az Out-of-Memory-állapot megszakíthatta a PHP-t, miközben a belső kéradatok csak részben voltak inicializálva, és a takarítás az érvénytelen adatokat érvényesként kezelte. A kihasználás részleteit nem tesszük közzé; a rés besorolása a CVE-2026-109618 oldalon található.
Az új puha és kemény memóriahatár
A 2026. október 21-i biztonsági kiadásokkal a PHP-projekt megváltoztatta a viselkedést. A kézikönyv szerint a memory_limit azóta puha határ: egy kérés, amely túllépi, a legtöbb esetben még befejezhető, mielőtt a végzetes hiba következik. Egy külön kemény határ korlátozza, meddig mehet ez el.
| Direktíva | Alapérték | Módosítható | Jelentés |
|---|---|---|---|
memory_limit |
128M | INI_ALL | memóriahatár kérésenként, -1 = nincs határ |
memory_hard_limit_percent |
nincs beállítva | INI_ALL | kemény határ a memory_limit százalékában, új a 8.5.12, 8.4.27, 8.3.36, 8.2.35 óta |
post_max_size |
8M | INI_PERDIR | a POST-adatok maximális mérete |
upload_max_filesize |
2M | INI_PERDIR | egy feltöltött fájl maximális mérete |
Egy példa a kézikönyvből: memory_limit=128M és memory_hard_limit_percent=150 esetén a kemény határ 192 MB. A kézikönyv a direktívát egyben felismerési jegyként is megnevezi: ha egy PHP-verzió nem ismeri, érinti a CVE-2026-109618 és a CVE-2026-109619. Gyors teszt minden telepített PHP-verzióra:
php -r 'var_dump(ini_get("memory_hard_limit_percent"));'
# a bool(false) azt jelenti: ismeretlen direktíva
A backportot tartalmazó disztribúciós csomagoknál a csomag changelogja marad a mérvadó bizonyíték, ahogyan a PHP-verzió és javítási állapot helyes ellenőrzése oldalon le van írva. Ellenőrizze emellett külön a PHP-FPM binárist is, mert más verziójú lehet, mint a parancssor.
Memóriahatárok és PHP2Shell: amire most az adminisztrátoroknak figyelniük kell
A php.net CVE-2026-109618-ra vonatkozó átmeneti intézkedései szinte mind a memória és a kérésméretek körül forognak. Csökkentik a kockázatot, de nem helyettesítik a frissítést:
; FPM-pool, pl. /etc/php/8.3/fpm/pool.d/www.conf
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M ; 32M, ha feltöltések szükségesek
php_admin_value[upload_max_filesize] = 6M ; a post_max_size alatt tartandó
Három pont döntő. Először, egyetlen alkalmazás, könyvtár vagy másik pool sem állíthat be ismét véges határt; a php.net kifejezetten ezt az ellenőrzést követeli. Másodszor, a memory_limit=-1 értékű szolgáltatásnak kívülről, konténeren vagy cgroupon keresztül kell határt kapnia, a php.net szerint lehetőleg úgy, hogy csak az érintett worker álljon le. Az RLIMIT_AS és az RLIMIT_DATA a php.net szerint alkalmatlan. Harmadszor, a php.net korlátokat ajánl a webszerveren vagy a proxyn a kérés méretére, a mezők számára, a multipart-részekre, a fejlécekre és a beágyazási mélységre.
A kívülről érkező memóriahatár nélküli memory_limit=-1 nagy terhelésnél teljesen megbéníthat egy szervert. Az átmeneti intézkedéseket csak csomagként, és csak a frissítésig alkalmazza.
Hogyan állíthatja be a határt systemd-vel, azt a Memóriahatárok systemd-vel és cgroupokkal cikk mutatja; a mindennapi tartós megoldást a A memory_limit helyes beállítása írja le.
Hogyan segít konkrétan a PHP SOS?
A PHP-javítási szolgáltatáson keresztül így járunk el:
- Az állomány ellenőrzése: Felmérjük a szerveren lévő minden PHP-verziót, CLI, FPM és Apache-modul szerint külön, és teszteljük, hogy a javított verzió fut-e.
- A memóriahatárok rendezése: Megvizsgáljuk, hol állítják be mindenütt a
memory_limit-et, és úgy alakítjuk ki a pool- és rendszerhatárokat, hogy illeszkedjenek egymáshoz. - Az átmenet biztosítása: Ahol a frissítést még akadály gátolja, a php.net intézkedéseit teljes körűen és felülírás ellen zárva alkalmazzuk.
- Igazolás szolgáltatása: A verziókat, a csomagállapotokat és a konfigurációt az beavatkozás előtt és után írásban megkapja.
Gyakori kérdések
Mit jelent az „Allowed memory size exhausted” üzenet?
Egy szkript több memóriát akart lefoglalni, mint amennyit a memory_limit megenged. A PHP ilyenkor végzetes hibával megszakítja a folyamatban lévő kérést. A többi kérés és maga a szerver tovább fut.
Az egész szerverre érvényes a memory_limit?
Nem, a határ PHP-folyamatonként és kérésenként érvényes. Ha 20 FPM-worker fut egyenként 256 MB határral, együtt elméletileg több mint 5 GB-ot foglalhatnak le. Az összesített határt ezért a poolmérettel, a systemd-vel vagy konténerrel kell beállítani.
Mi a memory_hard_limit_percent?
Egy új direktíva, amely a PHP 8.5.12, 8.4.27, 8.3.36 és 8.2.35 verzióval jelent meg. Kemény határt állít a memory_limit százalékában, amelyet soha nem lehet túllépni. A memory_limit azóta maga is puha határ.
Véd a memory_limit=-1 a PHP2Shell ellen?
Csak részben. A php.net a beállítást a CVE-2026-109618 elleni átmeneti intézkedésként nevezi meg, kifejezetten teljes védelem nélkül. Feltétlenül szükséges hozzá kívülről érkező memóriahatár, és a frissítés továbbra is kötelező.