Röviden: A Zend Engine a PHP magja. A PHP-kódot opcode-okká fordítja, ezeket egy virtuális gépben hajtja végre, és közben kezeli a változókat és a memóriát. A PHP 4 óta minden PHP-telepítésben benne van. Mivel a PHP2Shell-rések ebben a magban vannak, nem segítenek a bővítmények vagy a CMS-frissítések, csak egy frissített PHP újraindítással.
Mi a Zend Engine?
A Zend Engine a PHP azon része, amely a tényleges munkát végzi. Minden más, például a webszerverhez való csatlakozás vagy az adatbázis-bővítmények, rá épül. Egy autó motorjához hasonlítható: a karosszéria és a felszereltség különbözik, a motor hajt mindent.
A PHP-kézikönyv szerint a név a fejlesztők, Zeev Suraski és Andi Gutmans keresztneveiből ered. A motort 1999 közepén mutatták be, és a 2000 májusában megjelent PHP 4.0-tól a PHP magja. Azóta többször is alapvetően átdolgozták.
| PHP-verzió | Motor | Legfontosabb változás a kézikönyv és az RFC-k szerint |
|---|---|---|
| PHP 4.0 (2000) | Zend Engine | első közös mag, jobb teljesítmény |
| PHP 5.0 (2004) | Zend Engine 2.0 | új objektummodell |
| PHP 7.0 (2015) | Zend Engine 3.0 | PHPNG: tömörebb adatszerkezetek, AST |
| PHP 8.0 (2020) | továbbfejlesztés | JIT-fordító az OPcache részeként |
Az építőelemek: fordító, virtuális gép, memória
A motor jól elkülönülő szakaszokban dolgozik. A PHP 7 óta az absztrakt szintaxisfáról szóló RFC szerint három fázis vezet a bájtkódig:
- Lexer: a forráskódot tokenekre bontja, például kulcsszavakra, változónevekre és karakterláncokra.
- Parser: a tokenekből absztrakt szintaxisfát (AST) épít, amely a program szerkezetét képezi le.
- Fordító: az AST-ből op-tömböket állít elő, vagyis opcode-listákat, fájlonként és függvényenként egyet.
- Végrehajtó (Zend VM): feldolgozza az opcode-okat. A JIT-RFC szerint minden opcode-hoz tartozik egy kezelőfüggvény, amely végrehajtja.
- Memóriakezelés: minden kéréshez memóriát foglal és szabadít fel, és közben felügyeli a
memory_limitkorlátját.
Egy szkript tokenjei a Tokenizer bővítménnyel láthatóvá tehetők. Ez ártalmatlan és tanulságos:
<?php
$code = '<?php $summe = 2 + 3; echo $summe;';
foreach (token_get_all($code) as $token) {
if (is_array($token)) {
echo token_name($token[0]), ': ', trim($token[1]), "\n";
} else {
echo 'Zeichen: ', $token, "\n";
}
}
A kimenet olyan bejegyzéseket mutat, mint a T_VARIABLE: $summe vagy a T_LNUMBER: 2. A parser pontosan ezekkel az építőelemekkel dolgozik tovább.
Hogyan kezeli a Zend Engine a változókat?
A kézikönyv szerint minden PHP-változó egy zval nevű tárolóban van. Ez tartalmazza a típust és az értéket, valamint kezelési adatokat, köztük egy hivatkozásszámlálót (refcount). A számláló azt mutatja, hány változónév mutat ugyanarra a tárolóra.
<?php
$a = str_repeat('x', 10);
$b = $a; // nincs másolás, mindkettő ugyanarra az értékre mutat
$b .= 'y'; // csak most másol (copy on write)
unset($a); // a számláló csökken, a memória felszabadul, ha eléri a 0-t
Ha a számláló eléri a nullát, a motor felszabadítja a memóriát. Az objektumok közötti körkörös hivatkozásokra emellett szemétgyűjtő (garbage collector) is van. Erről bővebben a Memóriakezelés a PHP-ban cikkben olvashat.
A PHP 7-hez készült PHPNG-átdolgozás éppen itt kezdődött. A Dmitry Stogov és Zeev Suraski által írt RFC szerint tömörebb adatszerkezetekről és az értékek ügyesebb ábrázolásáról volt szó. Az RFC 20–110 százalékos teljesítménynövekedést említett valós alkalmazásokban.
OPcache és JIT: a motor bővítményei
Gyorsítótár nélkül a motor minden szkriptet minden kérésnél újra lefordít. Az OPcache a kész opcode-okat a közös memóriában tartja készenlétben. A PHP 8.0 óta emellett JIT-fordító is van. Az RFC szerint a LuaJIT projekt egyik eszközén, a DynASM-en alapul, és a bájtkódból közvetlenül gépi kódot állít elő. A virtuális gép közben változatlan marad; a JIT csak a kezelők belépési pontjait cseréli le.
Az üzemeltetők számára ez azt jelenti: az OPcache és a JIT felgyorsítja a motort, de hibák esetén a viselkedésén nem változtat. A magban lévő rés aktív gyorsítótár mellett is megmarad.
Miért különösen súlyosak a motorban lévő rések
A két PHP2Shell-rés a PHP magjában van. A CVE-2026-109618 esetén egy memóriahiányos (out-of-memory) állapot megszakíthatja a motort, miközben a kérés adatai még csak részben vannak inicializálva; feltakarításkor az érvénytelen adatokat érvényesként kezeli a rendszer. A CVE-2026-109619 esetén belső állapot marad fenn a memória felszabadítása után, amelyet egy későbbi kérés ugyanabban a workerben felhasználhat.
A javított 8.5.12, 8.4.27, 8.3.36 és 8.2.35 verziók a PHP-kézikönyv szerint a memóriakorlát viselkedését is megváltoztatják: a memory_limit itt lágy korlát, egy új beállítás, a memory_hard_limit_percent pedig kemény felső határt szab. A kézikönyv felhívja a figyelmet arra, hogy az a verzió, amely ezt a beállítást nem ismeri, érintett a résekben. Backportokat használó disztribúcióknál emellett a csomag változásnaplója (changelog) számít.
A motor minden PHP-folyamatba be van töltve. A frissítés után ezért az összes PHP-FPM-workert, a mod_php-t használó Apache-folyamatot és a többi PHP-szolgáltatást újra kell indítani.
Hogy mi történik belül memóriahiány esetén, azt a memory_limit és out-of-memory cikk írja le. Magának a résnek a besorolása a CVE-2026-109618 oldalon található.
Hogyan segít konkrétan a PHP SOS?
- Verzió és csomagállapot ellenőrzése: Megállapítjuk, hogy a motor melyik állapota fut ténylegesen, beleértve a disztribúciója backportjait.
- Frissítés és újraindítás: A PHP-javítási szolgáltatáson keresztül telepítjük a frissítést, és ellenőrizzük, hogy egyetlen folyamat sem maradt régi kóddal.
- Memóriakorlátok észszerű beállítása: A
memory_limitértékét, az új kemény korlátot és a cgroup-korlátokat az Ön alkalmazásához igazítjuk. - Feltűnő jelenségek vizsgálata: A workerek összeomlásait vagy a 137-es kilépési állapotú folyamatokat besoroljuk, és megvizsgáljuk, állhat-e mögöttük támadás.
Gyakori kérdések
Honnan kapta a nevét a Zend Engine?
A név a fejlesztők keresztneveiből áll össze: Zeev Suraski és Andi Gutmans. A PHP-kézikönyv szerint a motort 1999 közepén mutatták be, és a PHP 4.0-tól, 2000 májusától a PHP magja volt.
A Zend Engine önálló termék, amelyet telepítenem kell?
Nem. A Zend Engine minden PHP-telepítés szerves része. Aki frissíti a PHP-t, automatikusan a motort is frissíti. A Zend cég kereskedelmi termékeihez nincs köze.
Mi az az opcode?
Az opcode a PHP virtuális gépének egyetlen utasítása, például egy összeadás, egy függvényhívás vagy egy értékadás. A fordító minden szkriptet ilyen utasítások sorozatává alakít, amelyeket aztán a motor feldolgoz.
Mi köze a Zend Engine-nek a memory_limit-hez?
A motor kezeli minden kérés memóriáját, és ügyel a memory_limit korlátjára. A 2026. 10. 21-i biztonsági kiadások óta ez a korlát a kézikönyv szerint lágy korlát, amelyet a memory_hard_limit_percent beállítással megadott kemény korlát egészít ki.