5.1.21C Programming

Safe alternatives — strncpy, snprintf, strlcpy

1,889 words9 min readdifficulty · medium

WHY do we need these at all?

char buf[8];
strcpy(buf, "hello world");   // 12 bytes into 8 → OVERFLOW

The fix: pass the size of buf so the copy can stop in time. Three tools do this, and they differ in one crucial detail each.


strncpy — the bounded copy with a trap


snprintf — formatting that can't overflow


strlcpy — the one that does it all right (BSD)

Figure — Safe alternatives — strncpy, snprintf, strlcpy

Comparison table (memorize this, skip the rest)

Function Caps to Always null-terminates? Return value Truncation check
strcpy nothing yes (if no overflow) dest ptr ❌ unsafe
strncpy n bytes NO dest ptr manual
snprintf size (incl. \0) YES would-be length r >= size
strlcpy size-1 YES strlen(src) ret >= size
Recall Feynman: explain to a 12-year-old

Imagine pouring water into a cup. strcpy keeps pouring even when the cup is full — water spills everywhere and ruins your desk (that's a crash or a hack). The "safe" pourers first ask "how big is the cup?" strncpy stops pouring but sometimes forgets to put the lid on (no '\0'). snprintf always leaves room for the lid and tells you "you wanted more than fit." strlcpy is the polite one: stops in time, always puts the lid on, and whispers how much you actually had. The size argument is the question "how big is the cup?" — never skip it.


Flashcards

What single extra argument makes the safe string functions safe?
The size of the destination buffer, so the copy can stop before overflowing.
When does strncpy fail to null-terminate?
When the source length is >= n (the size limit): it copies exactly n bytes and adds no '\0'.
What is the standard fix after a strncpy(dest, src, sizeof(dest)-1)?
Manually set dest[sizeof(dest)-1] = '\0'; to guarantee termination.
Why copy at most sizeof(dest)-1, not sizeof(dest)?
One byte must be reserved for the trailing '\0'; capacity − 1 is the max content.
Does snprintf always null-terminate?
Yes, as long as size > 0, it always writes a terminating '\0'.
What does snprintf return and how do you detect truncation?
It returns the number of chars it would have written (excluding '\0'); truncation happened iff return >= size.
How does strlcpy differ from strncpy?
strlcpy always null-terminates and doesn't zero-pad; it caps at size-1 and returns strlen(src).
Why is strlcpy not always usable?
It is non-standard (BSD origin); not on all platforms — glibc added it only in 2.38.
Given char b[8]; snprintf(b,8,"id=%d",12345); what is in b and what does it return?
b = "id=1234" (7 chars + null); returns 8, flagging truncation since 8 >= 8.
What memory bug do these functions prevent?
Buffer overflow — writing past the end of the destination array.

Connections

  • C strings and the null terminator
  • Buffer overflow and stack smashing
  • strcpy and sprintf (unsafe)
  • sizeof vs strlen
  • Format strings and printf family
  • Memory safety and undefined behavior

Concept Map

no size check causes

prevents

takes

takes

takes

when src short

trap when src fills

requires

uses

reserves slot for null

Buffer overflow

strcpy and sprintf

Pass destination size n

strncpy dest src n

snprintf

strlcpy

Pads with nulls if src short

No null if src fills buffer

Force terminate manually

Cap at C minus 1

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho, C mein char buf[8] ka matlab hai sirf 8 byte ki jagah — usse zyada likhoge to memory overflow ho jaati hai, aur yahi cheez crash aur hacking ka sabse bada kaaran hai. strcpy aur sprintf size check hi nahi karte, isliye unhe "unsafe" bolte hain. Safe versions ek extra argument maangte hain: destination ka size kitna hai? Bas yahi ek number poora khel hai.

Teen tools yaad rakho. strncpy(dest, src, n) zyada se zyada n byte copy karta hai — par ek dhokha hai: agar source poora bhar gaya (n ya usse bada), to woh '\0' (null terminator) nahi lagaata. Tabhi humesha khud se dest[sizeof(dest)-1] = '\0'; likhna padta hai, warna string ka end hi nahi milega aur strlen/printf garbage padhne lagenge.

snprintf(dest, size, fmt, ...) sabse aaram-daayak hai: yeh humesha null-terminate karta hai aur kabhi overflow nahi karta. Iska return value bataata hai ki kitne characters likhne the (chahe room na ho) — agar return >= size, samajh jaao truncation ho gaya. strlcpy(dest, src, size) BSD ka hai, donon achhi baatein karta hai (overflow nahi, null hamesha lagta hai) aur strlen(src) return karta hai — par yeh standard C mein nahi hai, har platform pe nahi milega.

Yaad rakhne ka mantra: "n forgets the knot, printf aur l always tie it." Matlab strncpy null bhool sakta hai, par snprintf aur strlcpy hamesha null laga dete hain. Capacity C mein content hamesha C-1 tak hi, kyunki ek byte null ke liye reserve hai.

Go deeper — visual, from zero

Test yourself — C Programming

Connections