Situação atual: PHP2Shell. Duas vulnerabilidades críticas do PHP (CVSS 9,2) permitem executar código malicioso sem autenticação. Patches disponíveis desde 21/10/2026.O que fazer agora →

A Zend Engine: o coração do PHP

A Zend Engine traduz o código PHP em opcodes e executa-o. Quem conhece os seus componentes percebe por que razão falhas no núcleo, como o PHP2Shell, só se corrigem com uma atualização do PHP.

Atualizado em 5 min de leituraConhecimento PHP

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:

  1. Lexer: decompõe o código-fonte em tokens, por exemplo palavras-chave, nomes de variáveis e cadeias de carateres.
  2. Parser: constrói a partir dos tokens uma árvore sintática abstrata (AST) que representa a estrutura do programa.
  3. Compilador: gera a partir da AST op-arrays, isto é, listas de opcodes, uma por ficheiro e função.
  4. Executor (Zend VM): processa os opcodes. Segundo o RFC do JIT, a cada opcode corresponde uma função handler que o executa.
  5. 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.

Importante

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.

Fontes

Contacto imediato

Cada hora conta. Escreva-nos agora.

Descreva brevemente o sistema, a versão do PHP e o que observou. Entramos em contacto consigo, esclarecemos a situação e trabalhamos remotamente até o incidente estar concluído e documentado.

Ajuda imediata