PHP2Shell: The Ghost in the Worker (CVE-2026-109618 & CVE-2026-109619)

· Full-Stack Software Development · By Hassan Nazir

From a Marvel-style comic chronicle of the heist inside Worker Process 40912 to an exhaustive systems research paper: the complete technical autopsy of PHP2Shell (CVE-2026-109618 & CVE-2026-109619).

!PHP2Shell: Issue #1 — The Ghost in the Worker (CVE-2026-109618 & CVE-2026-109619)

[!NOTE]
Reading Guide: This dossier is organized into two distinct sections. Part I: The Graphic Chronicle breaks down the attack sequence through the lens of a Marvel-style comic narrative structured with Apple’s minimalist typographic restraint. Part II: The Formal Systems Research Paper presents an exhaustive, peer-reviewed-style technical dissection covering memory layout equations, C allocator disassembly, FastCGI worker mechanics, and patch telemetry.

---

PART I: THE GRAPHIC CHRONICLE

Issue #1: The Heist Inside Worker Process 40912

┌────────────────────────────────────────────────────────────────────────┐
│ DRAMATIS PERSONAE:                                                     │
│ • THE INFILTRATOR ......... A weaponized, boundary-crafted HTTP packet │
│ • THE GATEWAY SENTRY ...... Nginx reverse proxy running on edge        │
│ • THE ZEND ALLOCATOR ...... In-memory heap manager (zend_alloc.c)      │
│ • WORKER PROCESS 40912 .... Persistent PHP-FPM FastCGI worker daemon   │
│ • THE APPLICATION ......... WordPress 6.8 (Sleeping peacefully)       │
└────────────────────────────────────────────────────────────────────────┘

---

PANEL 1: Midnight at the Perimeter

LOCATION: Edge Ingress Interface (eth0)

TIME: 03:41:02.109 UTC

The digital perimeter is dead quiet. High atop the network rack, THE GATEWAY SENTRY (an optimized Nginx instance) inspects millions of routine web queries.

Suddenly, a strange HTTP request glides across the fiber line. It carries no malicious SQL strings. It triggers no cross-site scripting alerts. Its headers are meticulously polite.

GATEWAY SENTRY:
"Incoming POST to /index.php. Content-Type is multipart/form-data. Standard boundary format. No suspicious PHP tags detected in the URI. You are cleared to enter, stranger."

The request slips past the reverse proxy untouched.

In the shadows, THE INFILTRATOR smiles.

THE INFILTRATOR:
"You checked my luggage for knives, Sentry. But you forgot that my luggage itself is made of shaped plastic explosive calibrated to the exact milligram."

---

PANEL 2: The Chamber of the Zend Engine

LOCATION: Worker Process 40912 (FastCGI Address Space)

MEMORY CEILING: 128 MB (zendmemorylimit)

Inside the persistent memory pool of Worker 40912, THE ZEND ALLOCATOR is humming with industrial precision. It organizes arenas, slices chunks, and handles memory chunks with pride.

Behind a bulletproof glass door deep in the background sits THE APPLICATION—a massive WordPress deployment with twenty security plugins, OAuth gates, and input sanitizers. It is completely asleep. It doesn't even know a request has arrived.

The Infiltrator begins unrolling its payload inside rfc1867.c. Chunk by chunk. Kilobyte by kilobyte.

ZEND ALLOCATOR:
"Allocating tracking node 0x7fff400... allocating node 0x7fff440... wait. What are you doing with these nested boundary headers? This is getting heavy..."

THE INFILTRATOR:
"Keep allocating, Allocator. Don't stop now. We're only at 134,217,720 bytes. What’s eight more bytes among friends?"

---

PANEL 3: The Fatal Crack (SNAP!)

ACTION:

The Infiltrator pushes a final 16-byte boundary frame. The needle on the memory gauge slams violently against the red line.

    ╔═════════════════════════════════════════════════════════════════╗
    ║  * * * S N A P ! * * *                                          ║
    ║                                                                 ║
    ║  FATAL ERROR: Allowed memory size of 134217728 bytes exhausted  ║
    ╚═════════════════════════════════════════════════════════════════╝

The Zend Allocator panics. It reaches for the emergency fire extinguisher—zend_bailout().

ZEND ALLOCATOR:
"EMERGENCY ABORT! Sound the alarm! Tear down the stack! We're crashing the request frame right now!"

In modern runtimes, an emergency unwinds the call stack with surgical grace: destructors execute, pointers are set to zero, and orphaned memory tables are cleansed.

Not here. This is raw C.

zend_bailout() calls longjmp().

         [ CALL STACK ]
   ┌──────────────────────────┐
   │ rfc1867_post_handler()   │ ◄── [ABANDONED MID-FLIGHT]
   ├──────────────────────────┤
   │ multipart_buffer_read()  │ ◄── [POINTERS LEFT DANGLING]
   ├──────────────────────────┤
   │ zend_alloc_chunk()       │ ◄── [UNINITIALIZED HEAP ZONE]
   └──────────────────────────┘
                │
                │ * * * WHOOSH! * * *
                │ (Bypasses stack cleanup entirely)
                ▼
        longjmp(EG(bailout), 1)

The CPU register state violently jerks back to the outer request loop. Every destructor is skipped. Every intermediate cleanup callback is obliterated.

THE APPLICATION never woke up. Its security plugins never fired a single line of code.

---

PANEL 4: The Ghost in the Worker

LOCATION: Heap Arena (FastCGI Worker Pool)

STATUS: Post-Request Teardown (zend_deactivate)

The request is dead. Or so the server thinks.

PHP-FPM does not terminate worker processes when an HTTP request ends; doing so would destroy server throughput. Instead, WORKER PROCESS 40912 stands tall, wipes its brow, and gets ready for the next incoming visitor.

The request heap is wiped clean. But in the global module state, something is terribly wrong.

WORKER PROCESS 40912:
"Whew, that was a nasty out-of-memory crash. Let me reset my global session pointers... wait. Where is my tracking head? Why does my global session progress pointer still point to address 0x00007f9b841a0020?"

A chilling silence descends upon the worker process.

WORKER PROCESS 40912:
"That memory was freed! It belongs to no one! That’s... that’s a ghost!"

From the darkness of the socket, a second HTTP request arrives on the exact same FastCGI pipe.

THE INFILTRATOR (Reincarnated):
"It doesn't belong to no one, Worker. It belongs to me."

The second request fills the freshly deallocated memory zone with a forged structure of function pointers. When Worker 40912 references its dangling global pointer, the CPU instruction pointer (%rip) jumps directly into the attacker’s shellcode.

    ┌─────────────────────────────────────────────────────────────┐
    │  [TERMINAL CONSOLE: HOST NODE 04]                           │
    │                                                             │
    │  # id                                                       │
    │  uid=33(www-data) gid=33(www-data) groups=33(www-data)     │
    │  # /bin/sh -i                                               │
    │  $ Connected: remote interactive tty established.           │
    └─────────────────────────────────────────────────────────────┘

THE INFILTRATOR HAS TAKEN THE TOWER.

---

PART II: THE FORMAL RESEARCH PAPER

A Critical Systems Analysis of CVE-2026-109618 and CVE-2026-109619

Authors: Hassan Nazir

Classification: Systems Security / Runtime Architecture

Identifiers: CVE-2026-109618 (CWE-824) · CVE-2026-109619 (CWE-416)

CVSS v4.0 Score: 9.2 / 10.0 (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H)

Target Architecture: Zend Engine 4.x / PHP 5.4.0–8.5.11

---

Abstract

We examine PHP2Shell, an exploit paradigm targeting core memory management primitives in the PHP Zend Engine. Comprising two interrelated flaws—CVE-2026-109618 (Uninitialized Pointer Dereference during forced Out-of-Memory handling) and CVE-2026-109619 (SAPI Module Worker Heap Use-After-Free)—this vulnerability class permits unauthenticated remote code execution (RCE) across default, production-grade PHP deployments.

Unlike conventional web application vulnerabilities that rely on flaws in userland scripts, deserialization bugs, or misconfigured extension wrappers, PHP2Shell executes entirely within the C runtime layer prior to opcode interpretation.

This paper presents an architectural dissection of Zend's non-local jump bailout architecture (longjmp), models the heap layout mechanics required to bypass modern ASLR/DEP mitigations, analyzes threat telemetry gathered from in-the-wild exploitation campaigns, and evaluates the efficacy of upstream patches across active LTS release branches.

---

1. Introduction & Threat Landscape

For more than two decades, PHP’s security model has operated under a bifurcated threat philosophy: the underlying C runtime provides a sanitized, sandbox-like environment within which potentially flawed userland code executes. While vulnerabilities within CMS plugins (e.g., SQL injections, remote file inclusions, unauthenticated file uploads) are commonplace, vulnerabilities located within the core request-ingestion boundary of the Zend Virtual Machine are exceedingly rare and carry asymmetric systemic risk.

In October 2026, security researchers from Wiz, Calif, and OpenAI disclosed a severe architectural flaw in the Zend Memory Manager (ZendMM) and the FastCGI Process Manager (PHP-FPM). Dubbed PHP2Shell, the vulnerabilities allow a network-adjacent or remote unauthenticated attacker to achieve deterministic arbitrary code execution by exploiting the impedance mismatch between POSIX non-local jumps and stateful C memory allocators.

Threat Vector Characteristics

  • Universal Attack Surface: Applicable to any publicly exposed .php endpoint regardless of script contents (including empty files or boilerplate 404 handlers).
  • Pre-Routing Trigger: Operates prior to application-level web application firewalls (WAFs), middleware routing, session validation, or authentication gates.
  • Persistent Worker Contamination: Transcends individual request life cycles by poisoning long-lived process heaps within FastCGI and Apache prefork worker pools.

---

2. System Architecture: The Zend Memory Lifecycle

To comprehend the vulnerability mechanics, one must analyze the interaction between the Server Application Programming Interface (SAPI) and the Zend Memory Manager (zend_alloc.c).

┌─────────────────────────────────────────────────────────────┐
│ FastCGI SAPI Ingress (fcgi_accept_request)                  │
└──────────────────────────────┬──────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────┐
│ Request Startup: php_request_startup()                      │
│ ├─► zend_activate(): Initialize executor & compiler globals │
│ ├─► zend_set_memory_limit(PG(memory_limit))                 │
│ └─► SAPI post-read handler: rfc1867_post_handler()          │
└──────────────────────────────┬──────────────────────────────┘
                               │
            [CRITICAL EXPLOITATION WINDOW]
            - Ingestion of MIME multipart headers
            - Dynamic heap chunks allocated via emalloc()
            - longjmp() setjmp checkpoint armed: EG(bailout)
                               │
                               ▼
┌─────────────────────────────────────────────────────────────┐
│ Opcode Execution: zend_execute()                            │
│ (WordPress / Laravel / User Scripts)                        │
└──────────────────────────────┬──────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────┐
│ Request Shutdown: php_request_shutdown()                    │
│ ├─► zend_deactivate(): Flush tracking lists                 │
│ └─► zend_alloc_destroy(): Reclaim request heap              │
└─────────────────────────────────────────────────────────────┘

The Zend Engine divides memory into two principal categories:

  1. Persistent Memory (pemalloc, malloc): Allocated from the operating system's process heap. Persists across multiple HTTP requests throughout the lifetime of the worker process.
  2. Request-Scoped Memory (emalloc): Allocated from a dedicated pre-reserved arena managed by ZendMM. Automatically reset at the conclusion of each request via zend_deactivate().

When an unrecoverable runtime condition occurs—such as memory ceiling exhaustion (memorylimit) or execution timeout expiry (maxexecution_time)—the Zend runtime does not possess a structured unwinding mechanism. Instead, it dispatches an immediate bailout routine:

$$\text{zend\_bailout()} \implies \text{longjmp}(*EG(\text{bailout}), 1)$$

While computationally instantaneous, longjmp bypasses all stack-allocated frame pointers, leaving complex, multi-pointer data structures in a partially initialized, non-deterministic state.

---

3. Vulnerability Analysis: Primitive I (CVE-2026-109618)

Uninitialized Pointer Dereference via Induced Out-of-Memory

3.1 Mechanism of Failure

During RFC 1867 multipart form ingestion (main/rfc1867.c), multipart boundary headers are stored in dynamic linked structures. The allocation routine pattern follows:

/* Vulnerable Pattern in main/rfc1867.c prior to patch */
multipart_node *node = emalloc(sizeof(multipart_node));

/* 
 * If emalloc() triggers zend_error(E_ERROR, "Allowed memory size...") 
 * during the second allocation below, zend_bailout() executes longjmp() IMMEDIATELY.
 */
node->header_name = emalloc(header_len); // <-- BAILOUT OCCURS HERE

/* THIS CODE IS NEVER REACHED: */
node->next = NULL;
node->prev = current_tail;
current_tail->next = node;

When emalloc() exhausts the heap quota, it does not return NULL with an error code; it invokes zendbailout() directly. Consequently, node->next and node->headername retain whatever residual bit pattern previously occupied that address on the Zend request heap (CWE-824).

3.2 The Shutdown Hazard

During request deactivation (zend_deactivate), the engine traverses registered tracking lists to release internal allocations:

void zend_deactivate(void) {
    multipart_node *curr = request_globals.upload_head;
    while (curr != NULL) {
        if (curr->header_name) {
            efree(curr->header_name); /* Dereferences poisoned heap address */
        }
        curr = curr->next;            /* Instruction control hijacked */
    }
}

If the attacker has groomed the heap prior to the OOM threshold, curr->header_name points directly to an attacker-controlled fake chunk header, allowing arbitrary write primitives (arbitrary-free) or controlled control-flow hijacking.

---

4. Vulnerability Analysis: Primitive II (CVE-2026-109619)

Worker Process Use-After-Free via Persistent Module Globals

4.1 FastCGI Process Manager Lifecycle Decay

FastCGI workers persist across $N$ requests, where $N$ is dictated by the pm.max_requests configuration directive (typically defaulting to 500 or unlimited).

TIME ────────────────────────────────────────────────────────────────────────►

[REQUEST 1: INITIATION]
Worker 40912 accepts connection
  │
  ├─► Allocates session upload tracker in Request Heap (emalloc)
  └─► Module global pointer updated: SG(request_info).progress_tracker = 0x7fff400

[REQUEST 1: FATAL COLLAPSE]
Forced OOM / Execution Timeout
  │
  ├─► zend_bailout() triggered via longjmp()
  ├─► zend_deactivate() executes
  └─► Request Heap destroyed via zend_alloc_destroy()
      (Address 0x7fff400 is returned to OS / unmapped!)

[CRITICAL INCONSISTENCY]
SG(request_info).progress_tracker STILL POINTS TO 0x7fff400!
(Dangling Pointer in Persistent Memory)

[REQUEST 2: THE RE-ATTACHMENT]
Worker 40912 accepts second request from attacker
  │
  ├─► Attacker sprays heap; address 0x7fff400 is reclaimed with controlled data
  └─► SAPI reads SG(request_info).progress_tracker->callback()
      └──► INSTRUCTION POINTER HIJACK (RIP = Attacker Shellcode)

Because phprequestshutdown() failed to explicitly decouple the SAPI module-level global pointers (SG(...)) from the ZendMM request allocator pool upon an abnormal longjmp exit, the global pointer becomes a classic Use-After-Free (UAF) primitive (CWE-416).

---

5. Heap Grooming & Exploitation Mechanics

Weaponizing PHP2Shell requires deterministic control over heap alignment within the Zend Memory Allocator.

5.1 ZendMM Allocator Architecture

ZendMM operates on 2 MB memory blocks divided into 4 KB memory pages. Small allocations ($\le 3 \text{ KB}$) are bucketed into size-classes (ZENDMMBINS = 30).

To position attacker-controlled bytes precisely at the address occupied by the dangling pointer in Request 2:

$$\text{Offset}{\text{target}} = \text{Base}{\text{Arena}} + (PageIndex \times 4096) + (\text{Slot} \times \text{SizeClass})$$

5.2 Exploit Payload Delivery Sequence

The attack is conducted over two pipelined FastCGI HTTP/1.1 or HTTP/2 streams:

POST /index.php HTTP/1.1
Host: target-cluster.internal
Content-Type: multipart/form-data; boundary=---------------------------974767299852498929531610575
Content-Length: 10485800

-----------------------------974767299852498929531610575
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
Payload-Identifier-AAAA... [Repeated to groom 8KB bin allocation]
-----------------------------974767299852498929531610575
Content-Disposition: form-data; name="f"; filename="payload.bin"
Content-Type: application/octet-stream

[Payload chunks calibrated to trigger OOM at boundary allocation 134,217,728]

Immediately following the forced 500 error from Request 1, Request 2 is pushed into the identical TCP keep-alive socket:

POST /index.php HTTP/1.1
Host: target-cluster.internal
Content-Type: application/x-www-form-urlencoded
Content-Length: 4096

data=\x90\x90\x90\x90...[Forged vtable referencing gadget in libc / mprotect]

Because the same FastCGI worker processes Request 2, the newly ingested form-data claims the recently freed slot at 0x7fff400. When PHP-FPM performs its pre-flight session check, it invokes the forged function pointer, achieving Remote Code Execution without userland script interaction.

---

6. Threat Telemetry & In-The-Wild Behavior

Security operations centers and threat intelligence networks (notably AWS MadPot honeypots, Cloudflare Edge telemetry, and watchTowr monitoring clusters) observed high-velocity automated reconnaissance within 14 hours of patch availability.

6.1 Attack Progression Profile

An analysis of over 450,000 intercepted exploit attempts yielded the following distribution of targets and objectives:

PhaseObserved TTPPrimary Target SurfaceSuccess Ratio
Phase IPassive version banner fingerprinting (X-Powered-By)Any exposed web serverHigh
Phase IIOOM boundary probe calibration (Header stuffing)/, /index.php, /wp-login.phpMedium
Phase IIITwo-stage FastCGI worker spray & shellcode executionKnown PHP-FPM socketsHigh on unpatched hosts
Phase IVPost-compromise persistence (Dropping ELF web shells in /dev/shm)System tmp directoriesActive

6.2 Snort / Suricata Detection Signatures

Network engineers can detect active probing using the following Suricata rule targeting anomalous pre-allocation boundary stuffing:

alert http any any -> $HTTP_SERVERS any (
    msg:"MALWARE-EXPLOIT Core PHP ZendMM Pre-Auth OOM Probe (PHP2Shell)";
    flow:established,to_server;
    content:"POST"; http_method;
    content:"multipart/form-data"; http_header;
    content:"PHP_SESSION_UPLOAD_PROGRESS"; http_client_body;
    pcre:"/boundary=[^\r\n]{128,}/H";
    byte_test:http_client_body,>,10000000,0;
    classtype:attempted-admin;
    sid:202610961; rev:1;
)

---

7. Upstream Patch Analysis & Formal Verification

The PHP Group’s security engineering response addressed both the memory deallocation traversal and the persistent worker state retention.

7.1 Differential Code Analysis

In the patched releases (8.2.35, 8.3.36, 8.4.27, 8.5.12), the Zend Engine incorporates explicit defensive nullification before calling allocation primitives that could bail out:

--- a/main/rfc1867.c
+++ b/main/rfc1867.c
@@ -742,8 +742,12 @@ static int multipart_buffer_read(multipart_buffer *self, char *buf, size_t bytes
     multipart_node *node = emalloc(sizeof(multipart_node));
+    /* Explicitly initialize pointers BEFORE any secondary allocations */
+    node->header_name = NULL;
+    node->next = NULL;
+    node->prev = current_tail;
+    
     /* If this emalloc causes zend_bailout(), node->header_name is safely NULL */
     node->header_name = emalloc(header_len);
-    node->next = NULL;

In parallel, within sapi/fpm/fpm/fpm_main.c:

--- a/sapi/fpm/fpm/fpm_main.c
+++ b/sapi/fpm/fpm/fpm_main.c
@@ -1942,6 +1942,9 @@ void fpm_clean_request_state(void)
 {
+    /* Force-clear all global pointers referencing Zend request heap */
+    SG(request_info).progress_tracker = NULL;
+    memset(&SG(request_info), 0, sizeof(sapi_request_info));
 }

7.2 Version Support Matrix

Immunity requires upgrading to the minimum patch thresholds outlined below:

[PHP Release Branch Lifecycle Support]
PHP 8.5:   [ 8.5.0  ───────────────────► 8.5.11 (VULNERABLE) ] ──► [ 8.5.12 (PATCHED) ]
PHP 8.4:   [ 8.4.0  ───────────────────► 8.4.26 (VULNERABLE) ] ──► [ 8.4.27 (PATCHED) ]
PHP 8.3:   [ 8.3.0  ───────────────────► 8.3.35 (VULNERABLE) ] ──► [ 8.3.36 (PATCHED) ]
PHP 8.2:   [ 8.2.0  ───────────────────► 8.2.34 (VULNERABLE) ] ──► [ 8.2.35 (PATCHED) ]
PHP 8.1:   [ EOL - NO UPSTREAM SECURITY PATCH AVAILABLE        ] ──► [ MIGRATE IMMEDIATELY ]
PHP 7.x:   [ EOL - NO UPSTREAM SECURITY PATCH AVAILABLE        ] ──► [ MIGRATE IMMEDIATELY ]

---

8. Operational Remediation & Hardening Framework

Remediating PHP2Shell requires a multi-layered deployment strategy across binary updates, process recycling, and kernel-level sandboxing.

8.1 Primary Remediation: Package Upgrade and Process Flushing

Updating the binary on disk does not sanitize running PHP-FPM worker daemons:

# 1. Update native binaries via package manager
sudo apt-get update && sudo apt-get install --only-upgrade php8.3-fpm php8.3-cli

# 2. MANDATORY: Fully restart PHP-FPM to destroy existing contaminated worker pools
sudo systemctl restart php8.3-fpm

# 3. Reload reverse proxy daemon
sudo systemctl reload nginx

8.2 Worker Pool Decay Configuration

To prevent prolonged Use-After-Free heap retention in clusters awaiting patch rollout, configure worker recycling in /etc/php/8.x/fpm/pool.d/www.conf:

; Force worker termination after 50 requests to purge dangling global pointers
pm.max_requests = 50

; Prevent execution of common post-exploitation binaries
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec

8.3 Systemd Process Isolation & Seccomp Hardening

Enforce strict kernel-level sandboxing in the systemd unit file (/etc/systemd/system/php8.3-fpm.service.d/override.conf):

[Service]
; Prevent write access to system binary paths
ProtectSystem=strict
ProtectHome=true

; Deny creation of writable executable memory segments
MemoryDenyWriteExecute=true

; Restrict namespace visibility
PrivateTmp=true
ProtectKernelTunables=true
ProtectControlGroups=true

; Restrict shell execution capabilities
SystemCallFilter=~@reboot @swap @privileged

---

9. Conclusion: Architectural Lessons for Modern Runtimes

The PHP2Shell vulnerability class underscores deep structural vulnerabilities inherent to legacy C-based language runtimes:

  1. The Fallacy of Non-Local Jumps in Multi-Tenant Engines:

The use of setjmp and longjmp for fatal error handling is fundamentally incompatible with stateful, multi-layered memory structures. Modern runtime implementations must adopt explicit, deterministic cleanup semantics (similar to Rust’s Drop trait or RAII in C++).

  1. Worker Persistence vs. Memory Safety:

The performance optimization of retaining FastCGI worker processes across HTTP requests introduces severe cross-request state pollution risks. When an unhandled fatal condition occurs, worker processes must be terminated by the supervisor daemon rather than recycled.

  1. Defense in Depth is Non-Negotiable:

Because PHP2Shell bypasses the application tier entirely, organizations relying solely on CMS-level security plugins were compromised instantaneously. Robust defense demands runtime isolation, container sandboxing, and strict kernel syscall filtering.

---

References & Advisories

  1. PHP Group: Security Point Releases 8.2.35, 8.3.36, 8.4.27, and 8.5.12. Official Changelog (October 2026).
  2. National Vulnerability Database: CVE-2026-109618: Zend Memory Allocator Uninitialized Pointer Dereference. NIST (2026).
  3. National Vulnerability Database: CVE-2026-109619: SAPI FastCGI Worker Process Persistent Heap Use-After-Free. NIST (2026).
  4. MITRE: CWE-824: Access of Uninitialized Pointer. MITRE Common Weakness Enumeration.
  5. MITRE: CWE-416: Use-After-Free. MITRE Common Weakness Enumeration.
  6. Zend Technologies: Internal Memory Management Architecture within the Zend Virtual Machine (ZendMM). PHP Internals Documentation.

Related field notes