# PHP INI Parsing Stack Buffer Overflow Vulnerability

Off-by-one stack buffer overflow in PHP's zend_ini_do_op() when formatting a 32-bit INT_MIN result into a MAX_LENGTH_OF_LONG-sized buffer, triggered via crafted .ini file.

- Payout: $500
- Severity: medium
- Program: Internet Bug Bounty
- Credited: xixabangm4
- Disclosed: 2019-10-14
- CVE: CVE-2017-11628
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/248601
- Library page: https://bugbountylibrary.com/r/h1%3A248601
- Tags: domain:oss impact:dos kind:bounty platform:hackerone sev:medium tech:php technique:source-review vuln:dos vuln:memory-corruption

**Target:** PHP INI parser (zend_ini_do_op / parse_ini_file / parse_ini_string)
**Root cause:** str_result[MAX_LENGTH_OF_LONG] is one byte too small: the minimum 32-bit int "-2147483648" is 11 chars but MAX_LENGTH_OF_LONG is 11, so sprintf writes 12 bytes including NUL, overflowing by one byte.
**Steps:**
1. Build 32-bit PHP 5 <5.6.31 or PHP 7 <7.1.7.
2. Create input.ini containing `0=0&~2000000000` (bitwise NOT of 2000000000 yields INT_MIN).
3. Call `parse_ini_file($file, true, INI_SCANNER_NORMAL)` on it.
4. Observe `*** buffer overflow detected ***` abort under stack protector; without mitigation, one byte of adjacent stack variable/frame pointer is overwritten.
**How found:** Author read zend_long.h MAX_LENGTH_OF_LONG definitions and noticed the minimum values "-2147483648"/"-9223372036854775808" are exactly MAX_LENGTH_OF_LONG chars, then compared against str_result[MAX_LENGTH_OF_LONG] in zend_ini_do_op and realized the NUL terminator overflows by one byte.
**Exploitation:** Attacker supplies a crafted .ini file (or INI string via parse_ini_string) containing a bitwise expression whose result is INT_MIN; zend_sprintf writes the 12-byte string into an 11-byte stack buffer. With stack smashing protection this is immediate DoS; without it, one-byte overwrite of adjacent stack variable or frame pointer may enable code execution depending on compiler/optimization.
**Insight:** When auditing sprintf/strcpy into fixed buffers, check whether the buffer size accounts for the sign character and NUL terminator of the extreme value (INT_MIN/LONG_MIN), not just the digit count; bitwise operators in INI expressions are an easy way to force INT_MIN.
