# Heap Overflow Due To Integer Overflow

Signed int overflow in PHP mcrypt mdecrypt_generic computes tiny allocation from huge data_len, then memcpy overflows heap.

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

**Target:** PHP ext/mcrypt mdecrypt_generic
**Root cause:** data_len (unsigned) is cast to signed int for data_size computation; block-mode rounding and the non-block cast both wrap to a small value while memcpy still uses the full unsigned length.
**Steps:**
1. Open ext/mcrypt/mcrypt.c mdecrypt_generic; note `int block_size, data_size;` and `data_size = ((((int)data_len - 1) / block_size) + 1) * block_size;`
2. Pass data_len = 0xffffffff so data_size wraps to 0x20 (block mode) or 0 (non-block, `data_size = (int)data_len` giving -1, +1 = 0)
3. emalloc(data_size+1) allocates tiny buffer, then `memcpy(data_s, data, data_len)` copies 4294967295 bytes
4. Run provided PHP script with `str_repeat('A', 0xffffffff)` and mcrypt_module_open(MCRYPT_RIJNDAEL_256,'','cbc','') to trigger SIGSEGV in memcpy
**How found:** Source review of mcrypt.c: noticed data_size is signed int while data_len is unsigned, and the block-rounding formula plus the raw cast both allow wrap to a small allocation followed by a full-length memcpy.
**Insight:** In C extensions, audit every place an unsigned length is cast to signed int for size arithmetic (especially rounding formulas like `((len-1)/bs+1)*bs`) and confirm the same variable feeds memcpy; huge lengths near 0xffffffff wrap to small allocations.

