# The Zend Engine: The Heart of PHP

> The Zend Engine explained: compiler, opcodes, virtual machine, zval and memory management at the core of PHP, its versions and what it means for patches.

Source: https://phpsos.de/en/php/zend-engine/  
As of: 25/10/2026  
Provider: PHP SOS, PHP emergency help and server security. Immediate help via WhatsApp: https://wa.me/491736494914?text=Hello%20PHP%20SOS%2C%20we%20need%20help%20with%20our%20PHP%20server.%20Company%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**In short:** The Zend Engine is the core of PHP. It compiles PHP code into opcodes, executes them in a virtual machine and manages variables and memory while doing so. It has been part of every PHP installation since PHP 4. Because the PHP2Shell flaws lie in this core, plugins or CMS updates do not help; only an updated PHP with a restart does.

## What is the Zend Engine?

The Zend Engine is the part of PHP that does the actual work. Everything else, such as the connection to the web server or extensions for databases, builds on it. You can compare it to the engine of a car: bodywork and equipment differ, but the engine drives everything.

According to the PHP manual, the name is formed from the first names of the developers Zeev Suraski and Andi Gutmans. The engine was presented in mid-1999 and has been the core of PHP since PHP 4.0, released in May 2000. Since then it has been fundamentally reworked several times.

| PHP version | Engine | Most important change according to the manual and RFCs |
|---|---|---|
| PHP 4.0 (2000) | Zend Engine | first shared core, better performance |
| PHP 5.0 (2004) | Zend Engine 2.0 | new object model |
| PHP 7.0 (2015) | Zend Engine 3.0 | PHPNG: more compact data structures, AST |
| PHP 8.0 (2020) | further development | JIT compiler as part of OPcache |

## The building blocks: compiler, virtual machine, memory

The engine works in clearly separated stages. Since PHP 7, according to the RFC on the abstract syntax tree, there are three phases up to the bytecode:

1. **Lexer:** breaks the source code into tokens, such as keywords, variable names and strings.
2. **Parser:** builds an abstract syntax tree (AST) from the tokens, which represents the structure of the program.
3. **Compiler:** generates op arrays from the AST, that is, lists of opcodes, one per file and function.
4. **Executor (Zend VM):** works through the opcodes. According to the JIT RFC, each opcode has a handler function that executes it.
5. **Memory management:** reserves and releases memory for each request and monitors the limit from `memory_limit`.

The tokens of a script can be made visible with the Tokenizer extension. This is harmless and instructive:

```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";
    }
}
```

The output shows entries such as `T_VARIABLE: $summe` or `T_LNUMBER: 2`. The parser continues working with exactly these building blocks.

## How does the Zend Engine manage variables?

According to the manual, every PHP variable lives in a container called a zval. It holds type and value as well as management data, including a reference counter (refcount). The counter indicates how many variable names point to the same container.

```php
<?php
$a = str_repeat('x', 10);
$b = $a;        // no copying, both point to the same value
$b .= 'y';      // only now is it copied (copy on write)
unset($a);      // counter drops, memory is freed when it reaches 0
```

When the counter reaches zero, the engine releases the memory. For circular references between objects there is additionally a garbage collector. More on this in the article [Memory management in PHP](https://phpsos.de/en/php/speicherverwaltung/).

The PHPNG rework for PHP 7 started exactly here. According to the RFC by Dmitry Stogov and Zeev Suraski, it was about more compact data structures and a smarter representation of values. The RFC cited performance gains of 20 to 110 percent in real-world applications.

## OPcache and JIT: extensions of the engine

Without a cache, the engine recompiles every script on every request. The [OPcache](https://phpsos.de/en/php/opcache/) keeps the finished opcodes ready in shared memory. Since PHP 8.0 there is additionally a JIT compiler. According to the RFC, it is based on DynASM, a tool from the LuaJIT project, and generates machine code directly from the bytecode. The virtual machine remains unchanged in the process; the JIT only replaces the entry points of the handlers.

For operators this means: OPcache and JIT speed up the engine but change nothing about its behaviour in error conditions. A flaw in the core remains even with an active cache.

## Why flaws in the engine weigh especially heavily

The two PHP2Shell flaws lie in the core of PHP. With CVE-2026-109618, an out-of-memory condition can interrupt the engine while request data is only partially initialised; during clean-up, invalid data is then treated as valid. With CVE-2026-109619, internal state persists after memory has been released and can be used by a later request in the same worker.

According to the PHP manual, the corrected versions 8.5.12, 8.4.27, 8.3.36 and 8.2.35 also change the behaviour of the memory limit: `memory_limit` is a soft limit there, and a new setting `memory_hard_limit_percent` defines a hard upper limit. The manual points out that a version that does not know this setting is affected by the flaws. For distributions with backports, the package changelog counts in addition.

> **Important:**
> The engine is loaded in every PHP process. After the update, all PHP-FPM workers, Apache processes with mod_php and other PHP services must therefore be restarted.

What happens inside during a memory shortage is described in the article [memory_limit and out-of-memory](https://phpsos.de/en/php/out-of-memory/). The classification of the flaw itself is on [CVE-2026-109618](https://phpsos.de/en/php2shell/cve-2026-109618/).

## How does PHP SOS help?

- **Check version and package state:** We determine which engine state is actually running, including backports from your distribution.
- **Update and restart:** Through the [PHP patch service](https://phpsos.de/en/leistungen/php-patch-service/) we install the update and verify that no process with old code remains.
- **Set memory limits sensibly:** We tune `memory_limit`, the new hard limit and cgroup limits to your application.
- **Investigate anomalies:** We classify worker crashes or processes with exit status 137 and check whether an attack could be behind them.


## Frequently asked questions

**Where does the Zend Engine get its name?**  
The name is made up of the first names of its developers: Zeev Suraski and Andi Gutmans. According to the PHP manual, the engine was presented in mid-1999 and has been the core of PHP since PHP 4.0 in May 2000.

**Is the Zend Engine a separate product that I have to install?**  
No. The Zend Engine is an integral part of every PHP installation. Anyone who updates PHP automatically updates the engine as well. It has nothing to do with commercial products from the company Zend.

**What is an opcode?**  
An opcode is a single instruction for PHP's virtual machine, such as an addition, a function call or an assignment. The compiler translates every script into a sequence of such instructions, which the engine then works through.

**What does the Zend Engine have to do with memory_limit?**  
The engine manages the memory of each request and observes the limit from memory_limit. Since the security releases of 21 October 2026, according to the manual, this limit is a soft limit, complemented by a hard limit via memory_hard_limit_percent.

## Sources

- [PHP Manual: History of 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 Manual: Reference Counting](https://www.php.net/manual/en/features.gc.refcounting-basics.php)
- [PHP Manual: Core Settings (memory_limit)](https://www.php.net/manual/en/ini.core.php)
