# Zend Engine: srce PHP-a

> Zend Engine objašnjen: kompilator, opcodeovi, virtualni stroj, zval i upravljanje memorijom u jezgri PHP-a, njezine verzije i važnost za zakrpe.

Izvor: https://phpsos.de/hr/php/zend-engine/  
Stanje: 25.10.2026  
Pružatelj: PHP SOS, PHP hitna pomoć i sigurnost poslužitelja. Hitna pomoć putem WhatsAppa: https://wa.me/491736494914?text=Pozdrav%20PHP%20SOS%2C%20trebamo%20pomo%C4%87%20s%20na%C5%A1im%20PHP%20poslu%C5%BEiteljem.%20Tvrtka%3A%20%E2%80%A6%20Web-stranica%3A%20%E2%80%A6

**Ukratko:** Zend Engine jezgra je PHP-a. Prevodi PHP kod u opcodeove, izvršava ih u virtualnom stroju i pritom upravlja varijablama i memorijom. Od PHP-a 4 nalazi se u svakoj PHP instalaciji. Budući da PHP2Shell ranjivosti leže u toj jezgri, ne pomažu dodaci ni ažuriranja CMS-a, nego samo ažurirani PHP uz ponovno pokretanje.

## Što je Zend Engine?

Zend Engine je dio PHP-a koji obavlja stvarni posao. Sve ostalo, na primjer povezivanje s web-poslužiteljem ili ekstenzije za baze podataka, nadograđuje se na njega. Može se usporediti s motorom automobila: karoserija i oprema se razlikuju, a motor sve pokreće.

Prema PHP priručniku naziv je nastao od imena razvijatelja Zeeva Suraskog i Andija Gutmansa. Engine je predstavljen sredinom 1999., a od PHP-a 4.0, izišlog u svibnju 2000., bio je jezgra PHP-a. Otad je više puta temeljito prerađivan.

| PHP verzija | Engine | Najvažnija promjena prema priručniku i RFC-ovima |
|---|---|---|
| PHP 4.0 (2000.) | Zend Engine | prva zajednička jezgra, bolja učinkovitost |
| PHP 5.0 (2004.) | Zend Engine 2.0 | novi model objekata |
| PHP 7.0 (2015.) | Zend Engine 3.0 | PHPNG: kompaktnije podatkovne strukture, AST |
| PHP 8.0 (2020.) | daljnji razvoj | JIT kompilator kao dio OPcachea |

## Gradivni dijelovi: kompilator, virtualni stroj, memorija

Engine radi u jasno odvojenim stupnjevima. Od PHP-a 7 prema RFC-u o apstraktnom sintaktičkom stablu do bytecodea vode tri faze:

1. **Lexer:** rastavlja izvorni kod na tokene, na primjer ključne riječi, nazive varijabli i nizove znakova.
2. **Parser:** iz tokena gradi apstraktno sintaktičko stablo (AST) koje prikazuje strukturu programa.
3. **Kompilator:** iz AST-a stvara op-nizove, dakle popise opcodeova, po jedan za svaku datoteku i funkciju.
4. **Executor (Zend VM):** obrađuje opcodeove. Prema JIT RFC-u svakom opcodeu pripada funkcija rukovatelj koja ga izvršava.
5. **Upravljanje memorijom:** rezervira i oslobađa memoriju za svaki zahtjev i pritom nadzire granicu iz `memory_limit`.

Tokeni skripte mogu se učiniti vidljivima ekstenzijom Tokenizer. To je bezopasno i poučno:

```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";
    }
}
```

Ispis prikazuje unose poput `T_VARIABLE: $summe` ili `T_LNUMBER: 2`. Upravo s tim gradivnim dijelovima parser dalje radi.

## Kako Zend Engine upravlja varijablama?

Svaka PHP varijabla prema priručniku leži u spremniku zvanom zval. Sadrži tip i vrijednost te podatke za upravljanje, među ostalim brojač referenci (refcount). Brojač pokazuje koliko naziva varijabli upućuje na isti spremnik.

```php
<?php
$a = str_repeat('x', 10);
$b = $a;        // nema kopiranja, oba upućuju na istu vrijednost
$b .= 'y';      // tek sada se kopira (copy on write)
unset($a);      // brojač pada, memorija se oslobađa kad dosegne 0
```

Kada brojač dosegne nulu, engine oslobađa memoriju. Za kružne reference među objektima postoji dodatno sakupljač smeća (garbage collector). Više o tome u članku [Upravljanje memorijom u PHP-u](https://phpsos.de/hr/php/speicherverwaltung/).

Prerada PHPNG za PHP 7 počela je upravo ovdje. Prema RFC-u Dmitryja Stogova i Zeeva Suraskog radilo se o kompaktnijim podatkovnim strukturama i pametnijem prikazu vrijednosti. RFC je navodio dobitke u učinkovitosti od 20 do 110 posto u stvarnim aplikacijama.

## OPcache i JIT: proširenja enginea

Bez predmemorije engine svaku skriptu pri svakom zahtjevu prevodi iznova. [OPcache](https://phpsos.de/hr/php/opcache/) gotove opcodeove drži spremnima u zajedničkoj memoriji. Od PHP-a 8.0 postoji i JIT kompilator. Prema RFC-u temelji se na DynASM-u, alatu iz projekta LuaJIT, i strojni kod stvara izravno iz bytecodea. Virtualni stroj pritom ostaje nepromijenjen; JIT zamjenjuje samo ulazne točke rukovatelja.

Za operatere to znači: OPcache i JIT ubrzavaju engine, ali ne mijenjaju njegovo ponašanje pri pogreškama. Ranjivost u jezgri ostaje i s aktivnom predmemorijom.

## Zašto ranjivosti u engineu posebno teško pogađaju

Obje PHP2Shell ranjivosti leže u jezgri PHP-a. Kod CVE-2026-109618 stanje nedostatka memorije može prekinuti engine dok su podaci zahtjeva tek djelomično inicijalizirani; pri čišćenju se nevaljani podaci tada tretiraju kao valjani. Kod CVE-2026-109619 unutarnje stanje ostaje sačuvano nakon oslobađanja memorije i može ga iskoristiti kasniji zahtjev u istom workeru.

Ispravljene verzije 8.5.12, 8.4.27, 8.3.36 i 8.2.35 prema PHP priručniku mijenjaju i ponašanje granice memorije: `memory_limit` je tamo meka granica, a nova postavka `memory_hard_limit_percent` određuje tvrdu gornju granicu. Priručnik upozorava da je verzija koja ne poznaje tu postavku pogođena ranjivostima. Kod distribucija s backportovima dodatno vrijedi changelog paketa.

> **Važno:**
> Engine je učitan u svakom PHP procesu. Nakon ažuriranja zato se moraju ponovno pokrenuti svi PHP-FPM workeri, Apache procesi s mod_php-om i ostale PHP usluge.

Što se iznutra događa kod nedostatka memorije, opisuje članak [memory_limit i Out-of-Memory](https://phpsos.de/hr/php/out-of-memory/). Procjena same ranjivosti nalazi se na stranici [CVE-2026-109618](https://phpsos.de/hr/php2shell/cve-2026-109618/).

## Kako PHP SOS konkretno pomaže?

- **Provjeriti verziju i stanje paketa:** Utvrđujemo koje stanje enginea stvarno radi, uključujući backportove Vaše distribucije.
- **Ažurirati i ponovno pokrenuti:** Putem [PHP Patch usluge](https://phpsos.de/hr/leistungen/php-patch-service/) instaliramo ažuriranje i provjeravamo da nije ostao nijedan proces sa starim kodom.
- **Smisleno postaviti granice memorije:** Usklađujemo `memory_limit`, novu tvrdu granicu i cgroup granice s Vašom aplikacijom.
- **Istražiti neobičnosti:** Padove workera ili procese sa statusom izlaska 137 procjenjujemo i provjeravamo može li iza njih stajati napad.


## Česta pitanja

**Odakle Zend Engineu naziv?**  
Naziv je sastavljen od imena njezinih razvijatelja: Zeev Suraski i Andi Gutmans. Prema PHP priručniku engine je predstavljen sredinom 1999., a od PHP-a 4.0 u svibnju 2000. bio je jezgra PHP-a.

**Je li Zend Engine zaseban proizvod koji moram instalirati?**  
Ne. Zend Engine čvrsti je dio svake PHP instalacije. Tko ažurira PHP, automatski ažurira i engine. S komercijalnim proizvodima tvrtke Zend to nema nikakve veze.

**Što je opcode?**  
Opcode je pojedina naredba za virtualni stroj PHP-a, na primjer zbrajanje, poziv funkcije ili dodjela vrijednosti. Kompilator svaku skriptu prevodi u niz takvih naredbi koje engine zatim obrađuje.

**Kakve veze Zend Engine ima s memory_limit?**  
Engine upravlja memorijom svakog zahtjeva i pritom pazi na granicu iz memory_limit. Od sigurnosnih izdanja od 21. 10. 2026. ta je granica prema priručniku meka granica, dopunjena tvrdom granicom putem memory_hard_limit_percent.

## Izvori

- [PHP priručnik: Povijest PHP-a](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 priručnik: Brojanje referenci](https://www.php.net/manual/en/features.gc.refcounting-basics.php)
- [PHP priručnik: Osnovne postavke (memory_limit)](https://www.php.net/manual/en/ini.core.php)
