# Memory corruption due to missing check size in _php_math_number_format_ex()

PHP number_format() with huge decimal count and long thousand separator overflows the padding buffer in _php_math_number_format_ex(), causing a write out of bounds and SIGSEGV.

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

**Target:** PHP ext/standard/math.c _php_math_number_format_ex()
**Root cause:** The padding loop writes '0' backwards from a pointer t without verifying that the requested decimal count (dec) fits within the allocated buffer; a huge dec combined with a large thousand_sep causes writes before the buffer start.
**Steps:**
1. Call `number_format(1.337E+308, PHP_INT_MAX, "BBBBBBBBB", str_repeat("A", 0x0160b60c))` with memory_limit -1.
2. dec = PHP_INT_MAX makes topad enormous; the while(topad--) loop writes '0' bytes backwards via `*t-- = '0'` past the buffer.
3. Process crashes with SIGSEGV at math.c:1190 in _php_math_number_format_ex.
**How found:** Code review of _php_math_number_format_ex() spotted the unbounded `while (topad--) *t-- = '0'` padding loop; crafted a PoC with maximal dec and a large thousand separator to drive the write out of bounds.
**Insight:** In C string-formatting helpers, padding loops that walk a pointer backwards are prime overflow candidates when the pad count derives from an attacker-controlled integer; test with INT_MAX-style counts plus large separator strings to expose missing bounds checks.

