# str_repeat() sign mismatch based memory corruption

str_repeat() integer overflow creates corrupted ZVALs with negative string length, enabling PHP-level check bypass and memory corruption leading to potential RCE.

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

**Target:** PHP str_repeat() string function
**Root cause:** result_len is size_t but ZVAL_STRINGL expects signed int; input_len*mult overflows and implicit cast produces negative length in the string ZVAL.
**Steps:**
1. Call `str_repeat("a", 4294967294+1)` to overflow result_len into a negative signed length.
2. Observe corrupted ZVAL via gdb: str.len = -1 while type=6 (string).
3. Bypass checks: `echo strlen(str_repeat("a", 4294967294));` returns -2.
4. Trigger memory error: `strtoupper(str_repeat("a", 4294967294+1));` causes SIGSEGV in memcpy with user-controlled size 0xffffffff.
5. Other sinks: `md5(str_repeat("a", 4294967294-1));` and `str_repeat("a", 4294967294+1)."";` also crash.
**How found:** Code review of str_repeat() spotted the size_t result_len multiplied from input_len*mult and passed to RETURN_STRINGL/ZVAL_STRINGL which takes a signed int, suggesting an implicit cast overflow; confirmed with gdb on crafted inputs.
**Exploitation:** Attacker supplies a huge mult to str_repeat, producing a string ZVAL whose length is negative; downstream functions trusting the length perform oversized memcpy with attacker-controlled size, causing heap corruption that can be shaped into code execution.
**Escalation:** Corrupted ZVAL can be passed to string functions (strtoupper, md5, concatenation) to convert the length confusion into arbitrary memory corruption, potentially yielding local and remote code execution.
**Insight:** Audit PHP internal functions where a size_t length is passed to macros expecting signed int (ZVAL_STRINGL); huge mult values near 2^32 reveal sign-flip length confusion that bypasses strlen checks and feeds negative sizes into memcpy.

