5.3.12 · D3Build Systems & Toolchain

Worked examples — Address Sanitizer (ASan) — detecting buffer overflows at runtime

4,137 words19 min readBack to topic

Everything here reuses exactly one rule from the parent note. Let us pin it down so we never re-derive it. First, three names we will use constantly:

Notice the clean split: is a function that returns an address; is a number (the shadow value). We never write again — locates, is what we read.

Let me re-earn each symbol so a newcomer is never lost:

Every example below is just this formula, plugged in, plus one sanity re-read of the C.


The scenario matrix

We tabulate the classes of case ASan can meet. The goal: not one blank cell.

Cell Case class What is special Covered by
C1 In-bounds access, full green granule () must not fire Ex 1
C2 Overflow into a full redzone () classic heap overflow Ex 2
C3 Partial granule (), last valid byte boundary that must not fire Ex 3
C4 Partial granule, first poisoned byte boundary that must fire Ex 3
C5 Use-after-free (, was green) temporal, not spatial Ex 4
C6 Multi-byte access () straddling into poison, same granule matters, not just Ex 5
C7 Multi-byte access crossing a granule boundary one access, two shadow checks Ex 6
C8 Wild far pointer landing in another live object the false-negative ASan misses Ex 7
C9 Zero-size allocation malloc(0) degenerate size, still has redzone Ex 8
C10 Stack array overflow (compiler redzones) not heap; use-after-return cousin Ex 9
C11 Global buffer overflow + real-world word problem globals get redzones too Ex 10
C12 Exam twist: underflow (p[-1]) overflow on the low side Ex 11

Eleven examples, twelve cells (Ex 3 knocks out C3 and C4 — the two sides of one boundary).


Example 1 — In-bounds, fully green (cell C1)


Example 2 — Heap overflow into a redzone (cell C2)


Example 3 — The partial-granule boundary, both sides (cells C3 + C4)


Example 4 — Use-after-free (cell C5)


Example 5 — Multi-byte access straddling into poison, one granule (cell C6)


Example 6 — A multi-byte access that CROSSES a granule boundary (cell C7)


Example 7 — The wild far pointer ASan MISSES (cell C8)


Example 8 — Zero-size allocation (degenerate, cell C9)


Example 9 — Stack array overflow (cell C10)


Example 10 — Global buffer + real-world word problem (cell C11)


Example 11 — Exam twist: underflow, the low side (cell C12)


Recap: which cell fired?

Example Cell Verdict
1 C1 silent (correct)
2 C2 fire (heap overflow)
3 C3 / C4 silent / fire (boundary)
4 C5 fire (use-after-free)
5 C6 fire (multi-byte, same granule)
6 C7 silent then fire (boundary-crossing, two checks)
7 C8 silent (documented miss)
8 C9 fire (zero-size)
9 C10 fire (stack overflow)
10 C11 fire (global, offset 16)
11 C12 fire (underflow)
Recall Active recall

Compute the shadow value and the verdict for each:

  • malloc(3); p[2] ::: ; ; ? No → silent (legal).
  • malloc(3); p[3] ::: ; ? Yes → fire.
  • malloc(6); *(int*)(p+4) (4-byte read) ::: ; last byte ? Yes → fire.
  • malloc(8); p[100000] ::: may hit a green granule elsewhere → possibly silent (the gap).
  • malloc(16); *(int*)(p+6) (4-byte read, crosses boundary) ::: both endpoints in green granules → silent (legal).