Em resumo: A Zend Engine é o núcleo do PHP. Traduz o código PHP em opcodes, executa-os numa máquina virtual e gere nesse processo as variáveis e a memória. Desde o PHP 4 está presente em todas as instalações do PHP. Como as vulnerabilidades do PHP2Shell estão neste núcleo, não ajudam plugins nem atualizações do CMS, mas apenas um PHP atualizado com reinício.
O que é a Zend Engine?
A Zend Engine é a parte do PHP que faz o trabalho propriamente dito. Tudo o resto, como a ligação ao servidor web ou as extensões para bases de dados, assenta nela. Pode compará-la ao motor de um automóvel: a carroçaria e o equipamento diferem, mas o motor move tudo.
Segundo o manual do PHP, o nome foi formado a partir dos nomes próprios dos criadores, Zeev Suraski e Andi Gutmans. O motor foi apresentado em meados de 1999 e, a partir do PHP 4.0, lançado em maio de 2000, foi o núcleo do PHP. Desde então foi várias vezes profundamente revisto.
| Versão do PHP | Motor | Principal alteração segundo o manual e os RFC |
|---|---|---|
| PHP 4.0 (2000) | Zend Engine | primeiro núcleo comum, melhor desempenho |
| PHP 5.0 (2004) | Zend Engine 2.0 | novo modelo de objetos |
| PHP 7.0 (2015) | Zend Engine 3.0 | PHPNG: estruturas de dados mais compactas, AST |
| PHP 8.0 (2020) | evolução | compilador JIT como parte do OPcache |
Os componentes: compilador, máquina virtual, memória
O motor trabalha em fases claramente separadas. Desde o PHP 7, segundo o RFC sobre a árvore sintática abstrata, há três fases até ao bytecode:
- Lexer: decompõe o código-fonte em tokens, por exemplo palavras-chave, nomes de variáveis e cadeias de carateres.
- Parser: constrói a partir dos tokens uma árvore sintática abstrata (AST) que representa a estrutura do programa.
- Compilador: gera a partir da AST op-arrays, isto é, listas de opcodes, uma por ficheiro e função.
- Executor (Zend VM): processa os opcodes. Segundo o RFC do JIT, a cada opcode corresponde uma função handler que o executa.
- Gestão de memória: reserva e liberta memória para cada pedido e vigia nisso o limite de
memory_limit.
Os tokens de um script podem tornar-se visíveis com a extensão Tokenizer. É inofensivo e instrutivo:
<?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 saída mostra entradas como T_VARIABLE: $summe ou T_LNUMBER: 2. É com estes elementos que o parser continua a trabalhar.
Como gere a Zend Engine as variáveis?
Segundo o manual, cada variável PHP está num contentor chamado zval. Contém o tipo e o valor, bem como dados de gestão, entre eles um contador de referências (refcount). O contador indica quantos nomes de variáveis apontam para o mesmo contentor.
<?php
$a = str_repeat('x', 10);
$b = $a; // sem cópia, ambas apontam para o mesmo valor
$b .= 'y'; // só agora se copia (copy on write)
unset($a); // o contador desce, a memória é libertada ao chegar a 0
Quando o contador chega a zero, o motor liberta a memória. Para referências circulares entre objetos existe ainda um garbage collector. Mais sobre isto no artigo Gestão de memória no PHP.
A revisão PHPNG para o PHP 7 atuou precisamente aqui. Segundo o RFC de Dmitry Stogov e Zeev Suraski, tratava-se de estruturas de dados mais compactas e de uma representação mais hábil dos valores. O RFC indicava ganhos de desempenho de 20 a 110 por cento em aplicações reais.
OPcache e JIT: extensões do motor
Sem cache, o motor traduz cada script de novo a cada pedido. O OPcache mantém os opcodes prontos na memória partilhada. Desde o PHP 8.0 existe ainda um compilador JIT. Segundo o RFC, assenta no DynASM, uma ferramenta do projeto LuaJIT, e gera código máquina diretamente a partir do bytecode. A máquina virtual permanece inalterada; o JIT substitui apenas os pontos de entrada dos handlers.
Para os operadores isto significa: o OPcache e o JIT aceleram o motor, mas não alteram o seu comportamento perante erros. Uma falha no núcleo mantém-se mesmo com a cache ativa.
Porque é que as falhas no motor pesam especialmente
As duas vulnerabilidades do PHP2Shell estão no núcleo do PHP. No CVE-2026-109618, uma condição de falta de memória pode interromper o motor enquanto os dados do pedido estão só parcialmente inicializados; na limpeza, dados inválidos são então tratados como válidos. No CVE-2026-109619, o estado interno persiste depois de a memória ser libertada e pode ser usado por um pedido posterior no mesmo worker.
As versões corrigidas 8.5.12, 8.4.27, 8.3.36 e 8.2.35 alteram também, segundo o manual do PHP, o comportamento do limite de memória: memory_limit é aí um limite flexível, e uma nova definição memory_hard_limit_percent fixa um limite máximo rígido. O manual indica que uma versão que não conheça esta definição está afetada pelas vulnerabilidades. Em distribuições com backports conta ainda o changelog do pacote.
O motor está carregado em cada processo PHP. Depois da atualização, têm por isso de ser reiniciados todos os workers do PHP-FPM, os processos Apache com mod_php e os restantes serviços PHP.
O que acontece no interior perante uma falta de memória descreve-o o artigo memory_limit e falta de memória. O enquadramento da própria vulnerabilidade está em CVE-2026-109618.
Como ajuda concretamente a PHP SOS?
- Verificar a versão e o estado dos pacotes: Apuramos que versão do motor está realmente em execução, incluindo os backports da sua distribuição.
- Atualizar e reiniciar: Através do serviço de patches PHP aplicamos a atualização e controlamos que não sobra nenhum processo com código antigo.
- Definir limites de memória com critério: Ajustamos
memory_limit, o novo limite rígido e os limites de cgroup à sua aplicação. - Investigar anomalias: Avaliamos falhas de workers ou processos com estado de saída 137 e verificamos se pode haver um ataque por trás.
Perguntas frequentes
De onde vem o nome Zend Engine?
O nome compõe-se dos nomes próprios dos seus criadores: Zeev Suraski e Andi Gutmans. Segundo o manual do PHP, o motor foi apresentado em meados de 1999 e, a partir do PHP 4.0, em maio de 2000, foi o núcleo do PHP.
A Zend Engine é um produto à parte que tenho de instalar?
Não. A Zend Engine é parte integrante de qualquer instalação do PHP. Quem atualiza o PHP atualiza automaticamente também o motor. Não tem nada que ver com os produtos comerciais da empresa Zend.
O que é um opcode?
Um opcode é uma instrução isolada para a máquina virtual do PHP, por exemplo uma adição, uma chamada de função ou uma atribuição. O compilador traduz cada script numa sequência dessas instruções, que o motor depois processa.
O que tem a Zend Engine que ver com o memory_limit?
O motor gere a memória de cada pedido e respeita nisso o limite definido em memory_limit. Desde as versões de segurança de 21/10/2026, esse limite é, segundo o manual, um limite flexível, complementado por um limite rígido através de memory_hard_limit_percent.