# Information disclosure in mmap module - python 2.7.12

Python mmap resize() shrinks size but not pos, breaking the size>=pos invariant so read()/readline() leak adjacent memory pages.

- Payout: hidden
- Severity: low
- Program: Internet Bug Bounty
- Found by: aerodudrizzt
- Disclosed: 2019-10-13
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/174632
- Library page: https://bugbountylibrary.com/r/h1%3A174632
- Tags: area:oss domain:oss impact:data-leak kind:bounty platform:hackerone sev:low tech:python technique:source-review vuln:info-disclosure vuln:memory-corruption

**Target:** Python mmap module (read/readline/resize)
**Root cause:** resize() updates only self->size and ignores self->pos, so shrinking the map can leave pos > size, violating the size>=pos invariant the read paths rely on.
**Steps:**
1. mmap a file and advance the read position so pos is near the end
2. call resize() to shrink the mapping so size < pos
3. call read(): assert(size>=pos) passes in release builds, n=self->size-self->pos goes negative, is clamped to PY_SSIZE_T_MAX, and the read overruns into adjacent memory
4. or call readline(): memchr(start,'\n',self->size-self->pos) takes size_t length, making the bound negligible and reading past the mapping
5. PyString_FromStringAndSize(start, eol-start) returns the leaked adjacent-page bytes
**How found:** Security audit of the mmap module; noticed resize() only updates size and not pos, breaking the boundary-check invariant, then traced read()/readline() to see how the negative/underflowed length is handled.
**Exploitation:** Attacker-controlled Python code triggers resize() then read()/readline() to read bytes from an adjacent memory page; requires an adjacent mapped page or the read segfaults. Demonstrated on Windows 7.
**Insight:** When auditing resize/realloc-style APIs, check whether every coupled field (position vs size) is updated together; a stale position turns a signed subtraction into a huge unsigned length in memchr/memcpy-style calls.

