# Invalid read when wddx decodes empty boolean element

Empty <boolean/> tag in PHP wddx deserialization skips a stack push but still pops, causing type confusion and invalid read in php_base64_decode.

- Payout: hidden
- Severity: medium
- Program: Internet Bug Bounty
- Found by: fosec
- Disclosed: 2019-11-12
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/188661
- Library page: https://bugbountylibrary.com/r/h1%3A188661
- Tags: area:oss domain:oss impact:dos kind:bounty platform:hackerone sev:medium tech:php technique:source-review vuln:deserialization vuln:memory-corruption

**Target:** PHP wddx extension (wddx_deserialize)
**Root cause:** php_wddx_push_element only pushes a stack entry for <boolean> when atts is non-NULL, but php_wddx_pop_element unconditionally pops for </boolean>, so an empty <boolean/> pops the parent element's st_entry, leaving the stack top pointing at the wrong type.
**Steps:**
1. Craft WDDX XML with a parent element (e.g. <binary>) containing an empty <boolean/> child: `<binary><boolean/></binary>`.
2. Call `wddx_deserialize($xml)` on the packet.
3. The <boolean/> push is skipped (atts NULL), but </boolean> pops the <binary> st_entry.
4. On </binary>, php_wddx_pop_element reads the now-wrong stack top and passes it to php_base64_decode, dereferencing attacker-influenced memory (SIGSEGV at eax=0x41414141).
**How found:** Code review of push/pop handlers: noticed push is conditional on atts while pop is unconditional, then confirmed with a crafted packet and gdb backtrace showing SIGSEGV in php_base64_decode.
**Exploitation:** Attacker supplies a WDDX packet to wddx_deserialize; the empty boolean causes the parent's st_entry to be freed and the stack top to reference stale/wrong data, which is then treated as a string and base64-decoded, yielding an invalid read and potential memory corruption.
**Insight:** In XML/deserializer state machines, compare push and pop conditions for each tag: any tag whose push is conditional (on attributes) but whose pop is unconditional lets an attribute-less element desynchronize the stack and pop the parent's entry.

