# CVE-2020-10938-buffer overflow/out-of-bounds write in compress.c:HuffmanDecodeImage()

Signed integer overflow in ImageMagick's HuffmanDecodeImage lets a crafted FAX file drive x negative and write out of bounds on the heap.

- Payout: hidden
- Severity: critical
- Program: Internet Bug Bounty
- Found by: nathaniellives
- Disclosed: 2021-08-22
- CVE: CVE-2020-10938
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/816637
- Library page: https://bugbountylibrary.com/r/h1%3A816637
- Tags: area:os domain:desktop impact:integrity impact:rce kind:bounty platform:hackerone sev:critical tech:linux technique:source-review vuln:dos vuln:memory-corruption

**Target:** compress.c HuffmanDecodeImage() FAX decoder
**Root cause:** Signed x and count are added at line 566 without overflow check; repeated MW/MB/EX symbols push count near INT_MAX so x+count wraps negative, bypassing the columns bound and producing an invalid scanline offset.
**Steps:**
1. Craft FAX stream: emit TWId/TBId symbols to raise x to a small nonzero value below image->columns.
2. Emit repeated MWId/MBId/EXId symbols to grow count to INT_MAX-64.
3. Emit a TWId/TBId symbol so x+count overflows at `if ((x+count) > (long) image->columns)`.
4. Depending on color state, x becomes negative (invalid offset at `scanline[x++]=1`) or count exceeds columns, writing past scanline.
5. Build attached PoC generator (`make`), run to produce `poc.fax`, feed to ReadImage()->ReadFAXImage()->HuffmanDecodeImage().
**How found:** Code review of compress.c: noticed x and count are signed long, the bound check at line 566 is an unchecked signed addition, and Huffman symbol counts (MW/MB/EX) accumulate into count without limit, suggesting an integer overflow path.
**Exploitation:** Attacker supplies a crafted FAX file to any ImageMagick decode path. By alternating TWId/TBId symbols (which toggle color and adjust x) with MW/MB/EX symbols that drive count negative, the write offset can be steered byte-by-byte before/after the scanline heap buffer, enabling heap metadata corruption; all paths reach a free, so exploitation is practical.
**Escalation:** Color toggling plus the line-568 clamp lets the attacker skip uncontrolled writes and re-enter the TWId/TBId branch repeatedly, giving fine-grained single-byte writes around the heap buffer and into heap metadata.
**Insight:** In bitstream decoders, look for signed accumulators (run-length counts) added to a position then compared against a bound; if the sum can wrap, the clamp itself becomes the bypass. Toggle-state variables (like color) can be abused to re-enter the write branch for fine-grained control.
