# Zend Engine: srdce PHP

> Zend Engine vysvětlen: kompilátor, opcody, virtuální stroj, zval a správa paměti v jádru PHP, její verze a význam pro záplaty zranitelností.

Zdroj: https://phpsos.de/cs/php/zend-engine/  
Stav: 25.10.2026  
Poskytovatel: PHP SOS, Nouzová pomoc pro PHP a bezpečnost serverů. Okamžitá pomoc přes WhatsApp: https://wa.me/491736494914?text=Dobr%C3%BD%20den%2C%20PHP%20SOS%2C%20pot%C5%99ebujeme%20pomoc%20s%20na%C5%A1%C3%ADm%20PHP%20serverem.%20Firma%3A%20%E2%80%A6%20Web%3A%20%E2%80%A6

**Stručně:** Zend Engine je jádro PHP. Překládá kód PHP na opcody, provádí je ve virtuálním stroji a spravuje přitom proměnné a paměť. Od PHP 4 je součástí každé instalace PHP. Protože zranitelnosti PHP2Shell leží právě v tomto jádru, nepomohou pluginy ani aktualizace CMS, ale pouze aktualizované PHP s restartem.

## Co je Zend Engine?

Zend Engine je část PHP, která odvádí vlastní práci. Vše ostatní, například napojení na webový server nebo rozšíření pro databáze, na ní staví. Lze ji přirovnat k motoru auta: karoserie a výbava se liší, motor pohání všechno.

Podle příručky PHP je název složen z křestních jmen vývojářů Zeeva Suraskiho a Andiho Gutmanse. Engine byla představena v polovině roku 1999 a od PHP 4.0, vydaného v květnu 2000, tvořila jádro PHP. Od té doby byla několikrát zásadně přepracována.

| Verze PHP | Engine | Nejdůležitější změna podle příručky a RFC |
|---|---|---|
| PHP 4.0 (2000) | Zend Engine | první společné jádro, lepší výkon |
| PHP 5.0 (2004) | Zend Engine 2.0 | nový objektový model |
| PHP 7.0 (2015) | Zend Engine 3.0 | PHPNG: kompaktnější datové struktury, AST |
| PHP 8.0 (2020) | další vývoj | kompilátor JIT jako součást OPcache |

## Součásti: kompilátor, virtuální stroj, paměť

Engine pracuje v jasně oddělených stupních. Od PHP 7 jsou to podle RFC k abstraktnímu syntaktickému stromu tři fáze až po bytecode:

1. **Lexer:** rozloží zdrojový text na tokeny, například klíčová slova, názvy proměnných a řetězce.
2. **Parser:** sestaví z tokenů abstraktní syntaktický strom (AST), který zobrazuje strukturu programu.
3. **Kompilátor:** vytvoří z AST op-arrays, tedy seznamy opcodů, jeden pro každý soubor a funkci.
4. **Executor (Zend VM):** zpracovává opcody. Podle RFC k JIT patří ke každému opcodu funkce handleru, která jej provádí.
5. **Správa paměti:** vyhrazuje a uvolňuje paměť pro každý požadavek a hlídá přitom limit z `memory_limit`.

Tokeny skriptu lze zviditelnit pomocí rozšíření Tokenizer. Je to neškodné a poučné:

```php
<?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";
    }
}
```

Výstup ukazuje položky jako `T_VARIABLE: $summe` nebo `T_LNUMBER: 2`. S právě těmito stavebními prvky pracuje parser dál.

## Jak Zend Engine spravuje proměnné?

Každá proměnná PHP leží podle příručky v kontejneru zvaném zval. Obsahuje typ a hodnotu a také správní údaje, mimo jiné čítač referencí (refcount). Čítač udává, kolik názvů proměnných ukazuje na tentýž kontejner.

```php
<?php
$a = str_repeat('x', 10);
$b = $a;        // žádné kopírování, obě ukazují na stejnou hodnotu
$b .= 'y';      // teprve nyní se kopíruje (copy on write)
unset($a);      // čítač klesá, paměť se uvolní, když dosáhne 0
```

Když čítač dosáhne nuly, engine paměť uvolní. Pro kruhové odkazy mezi objekty existuje navíc garbage collector. Více v článku [Správa paměti v PHP](https://phpsos.de/cs/php/speicherverwaltung/).

Přepracování PHPNG pro PHP 7 se zaměřilo právě na toto. Podle RFC od Dmitryho Stogova a Zeeva Suraskiho šlo o kompaktnější datové struktury a šikovnější reprezentaci hodnot. RFC uvádělo zvýšení výkonu o 20 až 110 procent ve skutečných aplikacích.

## OPcache a JIT: rozšíření enginu

Bez cache engine překládá každý skript při každém požadavku znovu. [OPcache](https://phpsos.de/cs/php/opcache/) drží hotové opcody připravené ve sdílené paměti. Od PHP 8.0 existuje navíc kompilátor JIT. Podle RFC je založen na DynASM, nástroji z projektu LuaJIT, a vytváří strojový kód přímo z bytecodu. Virtuální stroj přitom zůstává nezměněn; JIT nahrazuje jen vstupní body handlerů.

Pro provozovatele to znamená: OPcache a JIT engine zrychlují, ale nic nemění na jejím chování při chybách. Zranitelnost v jádru zůstává i při aktivní cache.

## Proč chyby v enginu váží obzvlášť

Obě zranitelnosti PHP2Shell leží v jádru PHP. U CVE-2026-109618 může stav nedostatku paměti přerušit engine ve chvíli, kdy jsou data požadavku inicializována jen částečně; při úklidu jsou pak neplatná data považována za platná. U CVE-2026-109619 zůstává po uvolnění paměti vnitřní stav zachován a může ho využít pozdější požadavek ve stejném workeru.

Opravené verze 8.5.12, 8.4.27, 8.3.36 a 8.2.35 mění podle příručky PHP také chování limitu paměti: `memory_limit` je tam měkký limit a nové nastavení `memory_hard_limit_percent` určuje tvrdou horní hranici. Příručka upozorňuje, že verze, která toto nastavení nezná, je zranitelnostmi postižena. U distribucí s backporty rozhoduje navíc changelog balíčku.

> **Důležité:**
> Engine je načtena v každém procesu PHP. Po aktualizaci je proto nutné restartovat všechny workery PHP-FPM, procesy Apache s mod_php a další služby PHP.

Co se uvnitř děje při nedostatku paměti, popisuje článek [memory_limit a Out-of-Memory](https://phpsos.de/cs/php/out-of-memory/). Zařazení samotné zranitelnosti najdete na stránce [CVE-2026-109618](https://phpsos.de/cs/php2shell/cve-2026-109618/).

## Jak konkrétně pomáhá PHP SOS?

- **Zkontrolovat verzi a stav balíčku:** Zjistíme, jaký stav enginu skutečně běží, včetně backportů vaší distribuce.
- **Aktualizovat a restartovat:** Prostřednictvím [služby PHP-Patch](https://phpsos.de/cs/leistungen/php-patch-service/) nasadíme aktualizaci a ověříme, že nezůstal žádný proces se starým kódem.
- **Rozumně nastavit limity paměti:** Sladíme `memory_limit`, nový tvrdý limit a limity cgroup s vaší aplikací.
- **Prošetřit nápadnosti:** Pády workerů nebo procesy se stavem ukončení 137 zařadíme a ověříme, zda za nimi nemůže stát útok.


## Časté dotazy

**Odkud má Zend Engine své jméno?**  
Název vznikl z křestních jmen jejích vývojářů: Zeev Suraski a Andi Gutmans. Engine byla podle příručky PHP představena v polovině roku 1999 a od PHP 4.0 v květnu 2000 tvořila jádro PHP.

**Je Zend Engine samostatný produkt, který musím instalovat?**  
Ne. Zend Engine je pevnou součástí každé instalace PHP. Kdo aktualizuje PHP, aktualizuje automaticky i engine. S komerčními produkty společnosti Zend to nemá nic společného.

**Co je opcode?**  
Opcode je jednotlivý příkaz pro virtuální stroj PHP, například sčítání, volání funkce nebo přiřazení. Kompilátor přeloží každý skript do posloupnosti takových příkazů, které engine poté zpracuje.

**Co má Zend Engine společného s memory_limit?**  
Engine spravuje paměť každého požadavku a hlídá přitom limit z memory_limit. Od bezpečnostních vydání z 21. 10. 2026 je tento limit podle příručky měkký, doplněný tvrdým limitem přes memory_hard_limit_percent.

## Zdroje

- [Příručka PHP: Historie PHP](https://www.php.net/manual/en/history.php.php)
- [PHP RFC: PHPNG](https://wiki.php.net/rfc/phpng)
- [PHP RFC: JIT](https://wiki.php.net/rfc/jit)
- [Příručka PHP: Počítání referencí](https://www.php.net/manual/en/features.gc.refcounting-basics.php)
- [Příručka PHP: Základní nastavení (memory_limit)](https://www.php.net/manual/en/ini.core.php)
