{
  "verified_on": "2026-10-21",
  "repository": "https://github.com/php/php-src",
  "branch": "PHP-8.5",
  "first_fixed_release": "8.5.12",
  "commit": "31c0ea7d7ff1d1fccb6492e52dab544011628065",
  "commit_title": "Avoid state corruption via bailout",
  "parent": "dd830558ffb1ac8378e812b4db97626e6087de3f",
  "commit_url": "https://github.com/php/php-src/commit/31c0ea7d7ff1d1fccb6492e52dab544011628065",
  "license_url": "https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/LICENSE",
  "verification": "Selected lines verified against git show at the exact revision. Full raw upstream files byte-match local Git objects. Commit message explicitly names both CVEs and GHSA advisories. These are explanatory excerpts, not the complete patch.",
  "sources": [
    {
      "revision": "dd830558ffb1ac8378e812b4db97626e6087de3f",
      "file": "Zend/zend_alloc.c",
      "raw_url": "https://raw.githubusercontent.com/php/php-src/dd830558ffb1ac8378e812b4db97626e6087de3f/Zend/zend_alloc.c",
      "sha256": "18a0126d4c5f2d0a653c5b8382eaa41a594a6f575f97079d5a80ccd108f96751",
      "lines": 3591
    },
    {
      "revision": "31c0ea7d7ff1d1fccb6492e52dab544011628065",
      "file": "Zend/zend_alloc.c",
      "raw_url": "https://raw.githubusercontent.com/php/php-src/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_alloc.c",
      "sha256": "082d69a789f071accdf3cc120817fcb225e29caae13141151ef7135fc42c519e",
      "lines": 3994
    },
    {
      "revision": "dd830558ffb1ac8378e812b4db97626e6087de3f",
      "file": "Zend/zend_execute_API.c",
      "raw_url": "https://raw.githubusercontent.com/php/php-src/dd830558ffb1ac8378e812b4db97626e6087de3f/Zend/zend_execute_API.c",
      "sha256": "c69095a83b6b40a14bb9b1c26dcfa656aa8ee7c1f028b6ea76068032a03df693",
      "lines": 2013
    },
    {
      "revision": "31c0ea7d7ff1d1fccb6492e52dab544011628065",
      "file": "Zend/zend_execute_API.c",
      "raw_url": "https://raw.githubusercontent.com/php/php-src/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_execute_API.c",
      "sha256": "7db2e5bae1c54764ada568b678aa39171c62a545387518cdff0f1ac05e185582",
      "lines": 2037
    }
  ],
  "cards": [
    {
      "id": "anatomy-oom",
      "cve": "CVE-2026-109618",
      "title": "An interrupted operation. Invalid state.",
      "advisory_ref": "php-advisory-oom",
      "summary": "An allocation can fail while internal request data is only partly initialized. An immediate bailout skips the rest of that operation; shutdown can then encounter the unfinished state.",
      "steps": [
        "Request processing allocates memory",
        "OOM interrupts an operation",
        "Shutdown reaches invalid state"
      ],
      "before": "The removed allocator path ends in zend_bailout(). That abrupt exit can leave intermediate state inconsistent.",
      "after": "The added path records a pending OOM and signals the VM. The wider fix adds controlled unwinding and safe failure handling; it does not simply raise memory_limit.",
      "scope": "The advisory confirms pre-application exploitation on Apache mod_php. This excerpt illustrates the allocator redesign; the complete update also changes callers, parsers, and extensions.",
      "file": "Zend/zend_alloc.c",
      "excerpt_label": "Selected removed and added lines; intervening diff lines omitted",
      "before_url": "https://github.com/php/php-src/blob/dd830558ffb1ac8378e812b4db97626e6087de3f/Zend/zend_alloc.c#L418-L419",
      "after_url": "https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_alloc.c#L439-L441",
      "additional_url": "https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_alloc.c#L3891-L3944",
      "additional_label": "Follow the OOM handler",
      "rows": [
        {
          "kind": "removed",
          "old": 418,
          "new": null,
          "text": "\tzend_bailout();"
        },
        {
          "kind": "removed",
          "old": 419,
          "new": null,
          "text": "\texit(1);"
        },
        {
          "kind": "gap",
          "old": null,
          "new": null,
          "text": "… intervening diff lines omitted …"
        },
        {
          "kind": "added",
          "old": null,
          "new": 439,
          "text": "\tEG(delayed_oom).state = ZEND_OOM_STATE_PENDING;"
        },
        {
          "kind": "added",
          "old": null,
          "new": 440,
          "text": ""
        },
        {
          "kind": "added",
          "old": null,
          "new": 441,
          "text": "\tzend_atomic_bool_store_ex(&EG(vm_interrupt), true);"
        }
      ]
    },
    {
      "id": "anatomy-state",
      "cve": "CVE-2026-109619",
      "title": "One request ends. Its pointers survive.",
      "advisory_ref": "php-advisory-state",
      "summary": "A worker can keep global references to an earlier request’s freed memory. A later request can use those references before initialization replaces them. The producer and consumer must run in the same worker.",
      "steps": [
        "Request A leaves a global reference",
        "Request memory is released",
        "Request B touches stale state"
      ],
      "before": "Executor shutdown could leave error-related globals pointing at state that belonged to the completed request.",
      "after": "These additions clear the backtrace, recorded errors, error mode, and exception pointer during shutdown, before early processing of another request can reuse them.",
      "scope": "This is one state family. The full patch also changes session and extension lifecycle handling. Disabling a single session feature only removes selected attack paths.",
      "file": "Zend/zend_execute_API.c",
      "excerpt_label": "Added shutdown resets; selected contiguous lines",
      "before_url": "https://github.com/php/php-src/blob/dd830558ffb1ac8378e812b4db97626e6087de3f/Zend/zend_execute_API.c#L426-L431",
      "after_url": "https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_execute_API.c#L437-L445",
      "additional_url": "https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/ext/session/session.c#L3236-L3244",
      "additional_label": "See the early session reset",
      "rows": [
        {
          "kind": "added",
          "old": null,
          "new": 440,
          "text": "\tZVAL_UNDEF(&EG(last_fatal_error_backtrace));"
        },
        {
          "kind": "added",
          "old": null,
          "new": 441,
          "text": "\tEG(record_errors) = false;"
        },
        {
          "kind": "added",
          "old": null,
          "new": 442,
          "text": "\tEG(num_errors) = 0;"
        },
        {
          "kind": "added",
          "old": null,
          "new": 443,
          "text": "\tEG(errors) = NULL;"
        },
        {
          "kind": "added",
          "old": null,
          "new": 444,
          "text": "\tEG(error_handling) = EH_NORMAL;"
        },
        {
          "kind": "added",
          "old": null,
          "new": 445,
          "text": "\tEG(exception) = NULL;"
        }
      ]
    }
  ]
}
