# PHP yaml_parse/yaml_parse_file/yaml_parse_url Double Free

Double free in PHP yaml_parse error path when php_var_unserialize fails on a crafted !php/object value, enabling memory corruption and potential EIP control.

- Payout: $1,500
- Severity: high
- Program: Internet Bug Bounty
- Credited: johnleitch
- Disclosed: 2015-05-18
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/73256
- Library page: https://bugbountylibrary.com/r/h1%3A73256
- Tags: domain:oss impact:rce kind:bounty platform:hackerone sev:high tech:php technique:source-review vuln:deserialization vuln:memory-corruption

**Target:** yaml_parse/yaml_parse_file/yaml_parse_url in pecl yaml extension
**Root cause:** On php_var_unserialize() failure, PHP_VAR_UNSERIALIZE_DESTROY(var_hash) is called in the error branch and again before return, freeing var_hash twice.
**Steps:**
1. Craft YAML with invalid !php/object value: `a:  !php/object O:0:1` followed by `b: !php/object`
2. Call `yaml_parse($yaml)`
3. php_var_unserialize returns false, triggering first PHP_VAR_UNSERIALIZE_DESTROY
4. Second PHP_VAR_UNSERIALIZE_DESTROY before return causes double free
5. Heap grooming via document layout yields EIP control (DEP AV demonstrated)
**How found:** Code review of parse.c line 797 error path revealed the duplicate PHP_VAR_UNSERIALIZE_DESTROY call; crafted invalid !php/object YAML to force php_var_unserialize failure and confirmed crash in debugger.
**Exploitation:** Attacker supplies YAML to yaml_parse; invalid !php/object forces the error path, double-freeing var_hash. By manipulating document layout to shape heap memory, the freed chunk is reallocated with attacker-influenced data, leading to EIP control and arbitrary code execution (DEP access violation shown).
**Escalation:** Heap layout manipulation via crafted YAML document converts the double free into controlled EIP, escalating from crash to code execution.
**Insight:** Audit error/cleanup paths for double-free when a function both frees in an error branch and again at function exit; force the failure branch with malformed tagged values like !php/object.
