# An integer overflow bug in php_str_to_str_ex() led arbitrary code execution.

Integer overflow in PHP 7.1.0 strtr()/php_str_to_str_ex() on 32-bit lets attacker-controlled string bytes overwrite EIP, achieving arbitrary code execution.

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

**Target:** PHP ext/standard/string.c php_str_to_str_ex() via strtr()
**Root cause:** zend_string_alloc() is called with count*(str_len-needle_len)+ZSTR_LEN(haystack) without overflow check; on 32-bit the multiplication/addition wraps, allocating a too-small buffer that is then written past.
**Steps:**
1. Build PHP 7.1.0-dev on a 32-bit (i686) machine.
2. Run PoC: `$a = str_repeat('A', 65536); $b = str_repeat('ABCD', 32768); $c = array('AA'=> $b); strtr($a, $c);`
3. Observe SIGSEGV with `eip = 0x44434241` (bytes 'ABCD' from the replacement string).
4. Change the 'ABCD' replacement bytes to control EIP to an arbitrary address.
**How found:** Code review of ext/standard/string.c:3234 spotted the unchecked size arithmetic in zend_string_alloc(); crafted strtr() inputs to force the 32-bit wrap and confirmed EIP control in gdb.
**Exploitation:** Attacker supplies a large haystack and a replacement array whose key/value lengths make count*(str_len-needle_len)+len(haystack) wrap 32-bit; the undersized allocation is overflowed with attacker-controlled bytes, overwriting the saved return address/EIP with bytes from the replacement string, redirecting execution to an attacker-chosen address.
**Insight:** On 32-bit builds, audit length arithmetic in string-replacement helpers (count*(len-needle)+len) for wrap; the replacement string bytes land directly on the stack, so they become the EIP value.

