Secure Coding in C · beginner · ~20 min
Replace every unbounded string write with a bounded equivalent.
'Buffer safety' is the discipline that every write to a buffer is bounded by the destination's size. The opposite — writing until the source ends — is what makes C famous for crashes and exploits.
Roughly half the CVEs in C tools historically trace back to unbounded string writes. Replacing them all is the single highest-leverage hardening change.
The forbidden list. gets, strcpy, strcat, sprintf, scanf("%s") — never call these on attacker-controlled data.
The safe list. fgets(buf, sizeof buf, stdin), snprintf(buf, sizeof buf, ...), strlcpy, strlcat. Each takes the destination size; each NUL-terminates.
strncpy is NOT strlcpy. strncpy will not NUL-terminate when the source is exactly as long as the buffer. Worst of both worlds; avoid.
Pentester mindset. A strcpy call into a fixed-size local buffer with attacker-controlled input is the textbook stack-overflow primitive. Auditors scan for it.
Defensive coding habit. Add -Wformat-security to your CFLAGS and treat warnings as errors. Compile with -D_FORTIFY_SOURCE=2 to catch some unsafe calls at compile time.
/* good */
snprintf(dst, sizeof dst, fmt, ...);
strlcpy(dst, src, sizeof dst);
fgets(buf, sizeof buf, stdin);
C's classic string functions (strcpy, strcat, sprintf, gets, scanf "%s") write until they hit a NUL byte in the source, without checking the destination size. Every CVE in the OWASP Top 10 'memory-safety' bucket traces back to one of those. The fix is mechanical: use the bounded equivalent everywhere.
char buf[16];
snprintf(buf, sizeof buf, "%s", user_input); /* truncates safely */
/* never: strcpy(buf, user_input); */
char dst[64];
int n = snprintf(dst, sizeof dst, "User: %s (%d)", name, age);
if (n < 0 || (size_t)n >= sizeof dst){
/* truncation — handle defensively */
}
Compile every test build with -fsanitize=address. Any unbounded copy bug fires immediately with the offending line.
Bounded copies don't fix logic bugs (still need to check what's IN the buffer), but they eliminate the entire memory-corruption class.
Every CGI script, every command-line tool that takes a username, every HTTP server. The single most-audited C bug class.
snprintf. 3. Implement your own strlcpy and convince yourself the trailing NUL is always written.Never use the forbidden list. Always use the safe list. Compile with -D_FORTIFY_SOURCE=2 -Wformat-security -fsanitize=address.