The ups and downs of strlcpy()
Posted Jul 19, 2012 2:25 UTC (Thu) by
quotemstr (subscriber, #45331)
Parent article:
The ups and downs of strlcpy()
Microsoft came much closer to getting these sorts of functions right than the BSD people did. Consider strcpy_s and strncpy_s. strcpy_s's signature looks like this:
errno_t strcpy_s(
char *strDestination,
size_t numberOfElements,
const char *strSource
);
By default, the function checks that we're copying at most (numberOfElements - 1) bytes plus a terminating NULL into strDest. If we try to exceed this buffer, strcpy_s
crashes explicitly with the equivalent of abort(3). This way, we still deflect a potential security hole and turn it into a relatively safe and controlled (if inconvenient) crash, thereby closing some security holes without introducing new truncation-based attacks.
If you do want the truncation behavior, you can use strncpy_s:
errno_t strncpy_s(
char *strDest,
size_t numberOfElements,
const char *strSource,
size_t count
);
strncpy_s works just like strncpy, except 1) it has the same buffer-checking safeties as strncpy, 2) always NULL-terminates the destination buffer, aborting if there's not enough room, and 3) doesn't zero-fill the remainder of the buffer if strlen(strSource) < count. This function is useful enough on its own, but you can get strlcpy-like truncation behavior by passing the special value _TRUNCATE for the count parameter. In this case, when the input string is too long, strncpy_s truncates it and instead of aborting, returns the special value STRUNCATE.
By decoupling the output buffer size from the expected number of bytes to copy, we can sidestep a lot of the issues that this article raises for strlcpy. There are also neat C++ template overloads that let you call these functions and have the compiler fill in numberOfElements in the case that you're using C++ and strDestination is an array.
The singular flaw of the entire *_s family of functions is the _set_invalid_parameter_handler function, which allows you to turn off the abort behavior above. There's no good reason to do so, and nobody in practice does, making this family of functions a much better alterantive to strlcpy and friends.
(
Log in to post comments)