C / C++▸ Also on YouTube

Buffer Overflow: The Bug That Built the Hacking Industry

What happens when 12 bytes are written into an 8-byte buffer? In C, the extras spill into the next variable and the program never notices. In Rust, the program halts and tells you exactly why. The classic buffer overflow, from the stack to the panic.

3 min readLuChang Ning

Buffer Overflow: The Bug That Built the Hacking Industry#

Tip
Watch the video version of this article: https://youtu.be/Xp7AIVAYg00

Programming is just logic, right? Change variable A, and variable B should stay exactly the same.

But what if, by simply filling a small box with too much stuff, you could teleport to a part of the program you were never supposed to see?

Today we are dissecting the classic buffer overflow — the bug that built the hacking industry.

The stack is a stack of drawers#

In your computer's memory, variables are often stored directly next to each other on the stack. Think of the stack as a column of wooden drawers: one for your socks, and the one right below it for the secret bank safe.

Now, C is a very trusting language. If you tell C to put ten items into an eight-item drawer, C does not say no. C says, "I'll try my best."

The C disaster#

Watch what happens when that trust is misplaced:

c
int authenticated = 0;
char buffer[8];
strcpy(buffer, "OVERFLOWING");

Three lines, and none of them look dangerous. But "OVERFLOWING" is 11 characters long — 12 bytes once the NUL terminator is counted — and buffer has room for 8. strcpy has no idea how large the destination is. It is not even looking. It copies until it hits the end of the string.

The first 8 bytes fill the drawer. The remaining 4 do not simply vanish — they spill over the edge and crush whatever was stored in the next drawer down. In this layout, that happens to be authenticated:

text
stack (grows downward)

  [  buffer[8]  ]  ← 8 bytes, full
  [ OVERFLOWIN ]  ← the extras land here...
  [ G\0        ]  ← ...overwriting the variable below
  [ authenticated = 0 ]

authenticated is no longer zero. It now holds whatever bytes your overflow happened to spill — and if the code that follows only checks whether it is not zero, congratulations: you have just granted yourself access to your own program, without even trying.

This is not hypothetical. Buffer overflows in C and C++ are among the most exploited bug classes in history — the engine behind decades of worms, rootkits, and zero-days. The language gives you raw memory, and the language will not stop you from writing past the edge of it. No bounds check. No complaint. Not even a warning at runtime.

Rust intercepts#

Now let's attempt the same crime in Rust. Rust is the bodyguard who checks the size of every item before you are even allowed to touch the drawer:

rust
let mut buffer = [0u8; 8];
let data = [1u8; 10];
buffer.copy_from_slice(&data);

A fixed-size array of 8 bytes, and an attempt to copy 10 bytes into it. The moment the program reaches this line, Rust does not let the spill happen. It stops the entire universe instead:

text
thread 'main' panicked at src/main.rs:5:12:
copy_from_slice: source slice length (10) does not match destination slice length (8)

Read that error like a love letter, because it is one. C would have stayed silent while the bank safe was being crushed. Rust tells you exactly what went wrong, where it went wrong — file, line, and the full history of the call stack. It is loud, it is messy, and it is beautiful.

The philosophy#

This is the core of the Rust philosophy.

A C program is like a polite waiter who lets the kitchen burn down because he does not want to interrupt your soup. Rust is the bodyguard who tackles you to the ground the moment he sees a suspicious shadow.

Because for a Rust developer, a panic is a promise: I would rather the world end than overwrite a single byte of memory I am not supposed to touch.

A wall of red text is a rescue#

So the next time you see a wall of red text, remember: it is not a failure. It is a rescue.

That panic is the moment your program stopped itself one instruction before it became a vulnerability — the same vulnerability that C would have shipped silently, straight into production, straight into the hands of whoever found it first.

Note
There is a video version of this article with the full animation: https://youtu.be/Xp7AIVAYg00

Watch the video version

This article is also available as a video on @luchangningCodeHero.

Keep reading

Enjoyed this deep dive?

Read another article, or watch the video version on YouTube.