Search topics...

Why is strlen() sometimes not considered "safe" in C? How to make it safer? What is the newer safer function name?

0 upvotes
Practice with AISoon

strlen() is unsafe because it takes no bound. Its contract is "scan forward from the pointer until you find a NUL ('\0') byte, returning the count." If the buffer is not actually NUL-terminated — truncated input, a non-terminated fixed-size field, a corrupted/attacker-supplied buffer, or a binary blob — strlen keeps reading past the end of the buffer. This causes a buffer over-read: at best a wrong (too-large) length, at worst a crash (reading into an unmapped page) or an information-disclosure security vulnerability (it walks across adjacent memory). It can also be a denial-of-service issue if it scans a very long region.

How to make it safer: always provide a maximum length so the scan is bounded by the size of the buffer you actually own.

  • strnlen(s, maxlen) — POSIX.1-2008 (it is not part of ISO C — even C23 did not add it — though it is very widely available). Returns the smaller of the real string length or maxlen, and never reads more than maxlen bytes. This is the most common, portable safer replacement:

    c
    /* buf may not be NUL-terminated; never read past sizeof(buf) */
    size_t len = strnlen(buf, sizeof(buf));
  • strnlen_s(s, maxsize) / the Annex K bounds-checked interfaces (<string.h> with __STDC_LIB_EXT1__). The optional C11 Annex K "_s" family (e.g., strnlen_s, strcpy_s, strcat_s) adds explicit size parameters and runtime constraint handling. strnlen_s additionally returns 0 if s is NULL. (Note: Annex K is optional and not universally implemented — glibc does not ship it — so portability matters; strnlen is the more widely available choice.)

The general defensive practice: prefer the n-bounded / _s bounded variants (strnlen, strlcpy, snprintf) over the unbounded classics (strlen, strcpy, sprintf) whenever the data comes from outside your direct control or from a fixed-width field. (Note strncpy is length-bounded but does not NUL-terminate on truncation — and pads with NULs otherwise — so it still needs manual termination; strlcpy/snprintf are the genuinely safer copies.)