Undefined Behavior & Safety

why gets and unbounded strcpy are dangerous

Some tools are dangerous not because you might misuse them but because they CANNOT be used safely at all. In C's standard library, a handful of old string functions fall into this category: by their very design they write an amount of data that the CALLER cannot control, into a buffer of FIXED size. The mismatch makes a buffer overflow not a risk but a near-certainty as soon as the input is large enough.

The worst offender is gets(). It reads a line from standard input into a buffer, but it has no parameter for the buffer's size, so it keeps writing until it hits a newline no matter how big the input is. There is no possible buffer large enough to be safe against arbitrary input, which is why gets() was officially removed from the C standard in C11 — it is the rare function the committee deleted outright. strcpy(dst, src) is nearly as bad in practice: it copies characters from src until it reaches the null terminator, with zero regard for how big dst is, so a too-long src overflows dst. strcat has the same flaw when appending. The standard 'n' variants take a size and are safer: snprintf is the recommended way to format into a buffer because it never writes past the size you give and always null-terminates. strncpy takes a size too, but carries its own caveat: if the source is exactly as long as the limit it does NOT add a terminating null, leaving you with an unterminated string that later reads run past — so even the 'safe' function needs care.

Why this matters: these functions are not theoretical relics; they appear in tutorials, legacy code, and quick scripts, and they are behind a great many historical security breaches. The practical rules are blunt: never call gets() (use fgets with an explicit size, or getline); prefer snprintf for formatting into buffers; treat strcpy and strcat as overflow waiting to happen unless you have already proven the destination is large enough; and when you use strncpy, terminate the result yourself. The real lesson underneath is that the size of the destination must travel with the destination — a function that does not take it cannot be safe.

char buf[64]; gets(buf); /* NEVER: no size; removed from C11 */ strcpy(buf, untrusted); /* overflows if untrusted > 63 chars */ /* safer replacements */ fgets(buf, sizeof buf, stdin); /* bounded line read */ snprintf(buf, sizeof buf, "%s", src); /* bounded, always terminated */

gets() and unbounded strcpy take no destination size and cannot be made safe. fgets and snprintf take a size; prefer them.

strncpy is safer than strcpy but is NOT automatically null-terminating: if the source fills the buffer exactly, no terminator is written and you are left with an unterminated string. Always terminate the result yourself, or prefer snprintf.

Also called
unsafe string functionsgets()unbounded strcpy危險字串函式