# De Zend Engine: het hart van PHP

> De Zend Engine uitgelegd: compiler, opcodes, virtuele machine, zval en geheugenbeheer in de kern van PHP, hun versies en het belang voor patches.

Bron: https://phpsos.de/nl/php/zend-engine/  
Stand: 25-10-2026  
Aanbieder: PHP SOS, PHP-noodhulp en serverbeveiliging. Directe hulp via WhatsApp: https://wa.me/491736494914?text=Hallo%20PHP%20SOS%2C%20wij%20hebben%20hulp%20nodig%20met%20onze%20PHP-server.%20Bedrijf%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kort gezegd:** De Zend Engine is de kern van PHP. Ze vertaalt PHP-code naar opcodes, voert die uit in een virtuele machine en beheert daarbij variabelen en geheugen. Sinds PHP 4 zit ze in elke PHP-installatie. Omdat de PHP2Shell-lekken in deze kern zitten, helpen geen plug-ins of CMS-updates, maar alleen een bijgewerkte PHP met herstart.

## Wat is de Zend Engine?

De Zend Engine is het onderdeel van PHP dat het eigenlijke werk doet. Al het andere, zoals de koppeling met de webserver of extensies voor databases, bouwt erop voort. Je kunt haar vergelijken met de motor van een auto: carrosserie en uitrusting verschillen, de motor drijft alles aan.

Volgens de PHP-handleiding is de naam gevormd uit de voornamen van de ontwikkelaars Zeev Suraski en Andi Gutmans. De engine werd medio 1999 gepresenteerd en was vanaf PHP 4.0, verschenen in mei 2000, de kern van PHP. Sindsdien is ze meermaals fundamenteel herzien.

| PHP-versie | Engine | Belangrijkste wijziging volgens handleiding en RFC's |
|---|---|---|
| PHP 4.0 (2000) | Zend Engine | eerste gezamenlijke kern, betere prestaties |
| PHP 5.0 (2004) | Zend Engine 2.0 | nieuw objectmodel |
| PHP 7.0 (2015) | Zend Engine 3.0 | PHPNG: compactere datastructuren, AST |
| PHP 8.0 (2020) | doorontwikkeling | JIT-compiler als onderdeel van OPcache |

## De bouwstenen: compiler, virtuele machine, geheugen

De engine werkt in duidelijk gescheiden fasen. Sinds PHP 7 zijn het volgens de RFC over de abstracte syntaxisboom drie fasen tot de bytecode:

1. **Lexer:** ontleedt de broncode in tokens, bijvoorbeeld sleutelwoorden, variabelenamen en tekenreeksen.
2. **Parser:** bouwt uit de tokens een abstracte syntaxisboom (AST), die de structuur van het programma weergeeft.
3. **Compiler:** maakt uit de AST op-arrays, dus lijsten van opcodes, één per bestand en functie.
4. **Executor (Zend VM):** werkt de opcodes af. Volgens de JIT-RFC hoort bij elke opcode een handlerfunctie die hem uitvoert.
5. **Geheugenbeheer:** reserveert en geeft geheugen vrij voor elk verzoek en bewaakt daarbij de grens uit `memory_limit`.

De tokens van een script kunnen met de extensie Tokenizer zichtbaar worden gemaakt. Dat is onschuldig en leerzaam:

```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";
    }
}
```

De uitvoer toont vermeldingen als `T_VARIABLE: $summe` of `T_LNUMBER: 2`. Met precies deze bouwstenen werkt de parser verder.

## Hoe beheert de Zend Engine variabelen?

Elke PHP-variabele ligt volgens de handleiding in een container met de naam zval. Die bevat type en waarde en beheergegevens, waaronder een referentieteller (refcount). De teller geeft aan hoeveel variabelenamen naar dezelfde container wijzen.

```php
<?php
$a = str_repeat('x', 10);
$b = $a;        // niet kopiëren, beide wijzen naar dezelfde waarde
$b .= 'y';      // pas nu wordt gekopieerd (copy on write)
unset($a);      // teller daalt, geheugen komt vrij als hij 0 bereikt
```

Bereikt de teller nul, dan geeft de engine het geheugen vrij. Voor kringverwijzingen tussen objecten bestaat bovendien een garbage collector. Meer daarover in het artikel [Geheugenbeheer in PHP](https://phpsos.de/nl/php/speicherverwaltung/).

De herziening PHPNG voor PHP 7 zette precies hier in. Volgens de RFC van Dmitry Stogov en Zeev Suraski ging het om compactere datastructuren en een slimmere weergave van waarden. De RFC noemde prestatiewinsten van 20 tot 110 procent in echte toepassingen.

## OPcache en JIT: uitbreidingen van de engine

Zonder cache vertaalt de engine elk script bij elk verzoek opnieuw. De [OPcache](https://phpsos.de/nl/php/opcache/) houdt de kant-en-klare opcodes in het gedeelde geheugen klaar. Sinds PHP 8.0 is er bovendien een JIT-compiler. Volgens de RFC is die gebaseerd op DynASM, een hulpmiddel uit het LuaJIT-project, en maakt hij machinecode rechtstreeks uit de bytecode. De virtuele machine blijft daarbij ongewijzigd; de JIT vervangt alleen de instappunten van de handlers.

Voor beheerders betekent dat: OPcache en JIT versnellen de engine, maar veranderen niets aan haar gedrag bij fouten. Een lek in de kern blijft ook met een actieve cache bestaan.

## Waarom lekken in de engine bijzonder zwaar wegen

De twee PHP2Shell-lekken zitten in de kern van PHP. Bij CVE-2026-109618 kan een out-of-memory-toestand de engine onderbreken terwijl verzoekgegevens pas gedeeltelijk zijn geïnitialiseerd; bij het opruimen worden ongeldige gegevens dan als geldig behandeld. Bij CVE-2026-109619 blijft de interne toestand na het vrijgeven van het geheugen bestaan en kan die door een later verzoek in dezelfde worker worden gebruikt.

De verholpen versies 8.5.12, 8.4.27, 8.3.36 en 8.2.35 wijzigen volgens de PHP-handleiding ook het gedrag van de geheugengrens: `memory_limit` is daar een zachte grens, een nieuwe instelling `memory_hard_limit_percent` legt een harde bovengrens vast. De handleiding wijst erop dat een versie die deze instelling niet kent, door de lekken is getroffen. Bij distributies met backports telt bovendien de changelog van het pakket.

> **Belangrijk:**
> De engine is in elk PHP-proces geladen. Na de update moeten daarom alle PHP-FPM-workers, Apache-processen met mod_php en overige PHP-diensten opnieuw worden gestart.

Wat er van binnen gebeurt bij een geheugentekort, beschrijft het artikel [memory_limit en out-of-memory](https://phpsos.de/nl/php/out-of-memory/). De duiding van het lek zelf staat onder [CVE-2026-109618](https://phpsos.de/nl/php2shell/cve-2026-109618/).

## Hoe helpt PHP SOS concreet?

- **Versie en pakketstand controleren:** Wij stellen vast welke engine-stand daadwerkelijk draait, inclusief backports van uw distributie.
- **Bijwerken en herstarten:** Via de [PHP-patchservice](https://phpsos.de/nl/leistungen/php-patch-service/) installeren wij de update en controleren dat er geen proces met oude code overblijft.
- **Geheugengrenzen zinvol instellen:** Wij stemmen `memory_limit`, de nieuwe harde grens en cgroup-grenzen af op uw toepassing.
- **Opvallende zaken onderzoeken:** Crashes van workers of processen met exitstatus 137 beoordelen wij en we controleren of er een aanval achter kan zitten.


## Veelgestelde vragen

**Waar komt de naam Zend Engine vandaan?**  
De naam is samengesteld uit de voornamen van de ontwikkelaars: Zeev Suraski en Andi Gutmans. De engine werd volgens de PHP-handleiding medio 1999 gepresenteerd en was vanaf PHP 4.0 in mei 2000 de kern van PHP.

**Is de Zend Engine een apart product dat ik moet installeren?**  
Nee. De Zend Engine is vast onderdeel van elke PHP-installatie. Wie PHP bijwerkt, werkt automatisch ook de engine bij. Met commerciële producten van het bedrijf Zend heeft dat niets te maken.

**Wat is een opcode?**  
Een opcode is één enkele opdracht voor de virtuele machine van PHP, bijvoorbeeld een optelling, een functieaanroep of een toewijzing. De compiler vertaalt elk script naar een reeks van zulke opdrachten, die de engine vervolgens afwerkt.

**Wat heeft de Zend Engine met memory_limit te maken?**  
De engine beheert het geheugen van elk verzoek en let daarbij op de grens uit memory_limit. Sinds de beveiligingsreleases van 21-10-2026 is deze grens volgens de handleiding een zachte grens, aangevuld met een harde grens via memory_hard_limit_percent.

## Bronnen

- [PHP-handleiding: geschiedenis van 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)
- [PHP-handleiding: referentietelling](https://www.php.net/manual/en/features.gc.refcounting-basics.php)
- [PHP-handleiding: kerninstellingen (memory_limit)](https://www.php.net/manual/en/ini.core.php)
