# PyUnicode_FromFormatV crasher

PyUnicode_FromFormatV in Python 2 ignores width/precision when sizing buffers, causing stack and heap overflows via crafted format strings.

- Payout: hidden
- Severity: high
- Program: Internet Bug Bounty
- Found by: guido
- Disclosed: 2014-12-15
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/43443
- Library page: https://bugbountylibrary.com/r/h1%3A43443
- Tags: area:oss domain:oss impact:rce kind:bounty platform:hackerone sev:high tech:python technique:source-review vuln:memory-corruption

**Target:** CPython C API PyUnicode_FromFormatV in Objects/unicodeobject.c
**Root cause:** The size-computation loop never parses width/precision (the `*f == '%'` and `isdigit(*f)` conditions are mutually exclusive), so abuffersize stays 20 and n omits padding, while sprintf later honors width/precision.
**Steps:**
1. Call PyUnicode_FromFormat() with a format containing a width/precision specifier, e.g. `%100d` or `%100.100d`, and a matching int argument.
2. Size loop leaves width=0, so abuffersize=20 and realbuffer points to stack `char buffer[21]`.
3. makefmt builds the padded specifier and sprintf writes >20 bytes into realbuffer, overflowing the stack.
4. appendstring copies the padded output into `s`, sized from n which also omits width, overflowing the heap.
**How found:** Code reading of the size-computation loop versus the processing loop; noticed the `*f == '%'` check makes the following isdigit width parse dead code, and that width/precision are ignored in sizing but honored by sprintf.
**Exploitation:** Any caller passing attacker-influenced format strings to PyUnicode_FromFormat can trigger stack and heap corruption; the report notes potential code execution in such cases.
**Insight:** When auditing format-string builders, diff the sizing pass against the emission pass: any specifier feature parsed in one but not the other (width, precision, flags) yields an overflow.

