5 ms·
The only string manipulation function you need is snprintf, every other str* function is dumb
by Cloudef 4y ago
The only string manipulation function you need is snprintf, every other str* function is dumb
- adrian_b 4y agoUsing snprintf is equivalent with using strlcpy and also equivalent with using a strlen followed by a memcpy. As explained in the parent article, using something equivalent with strlen is inefficient when the source is much longer than the destination, because you do not need the length of the source, you just need to know that it is longer than the destination. Instead of defining yet another strcpy-like function, I would have preferred an alternative to strlen, taking 2 arguments, the size of the destination and a pointer to the source, and returning either the length of the source or an error when the source is longer than the provided size. Then every strcpy can be replaced with that strlen-replacement function followed by memcpy, and the same strlen replacement can be used with all other string functions, e.g. with strcat. POSIX 2008 has added the strnlen function ("size_t strnlen(const char *s, size_t maxlen);"), which does not have the inefficiency of strlen, by returning at most the size of the destination, but it does not signal an error to indicate truncation. You can still use strnlen, if you give it a size larger by 1 and you check the return value to detect an oversize source, but it is slightly less convenient than if the strnlen return value would have been defined like the return value of strscpy.
- saagarjha 4y agomemchr?
- adrian_b 4y agomemchr is less convenient even than strnlen, because it returns a pointer, so you must subtract 2 pointers to get the size that needs to be used in memcpy. memchr is indeed an alternative for someone who would need to use some old libc, without the strnlen function. The strscpy function is available only inside the Linux kernel, but strnlen should be available in any environment that conforms to POSIX 2008, so strnlen + memcpy is what I would recommend for copying null-terminated strings in any C program.
- saagarjha 4y agoAh, I didn't spot that strnlen had made it into POSIX. Nice!
- JdeBP 4y agoEfficiency is not the goal. Security and safety are. strlen() in kernel code on an (intentionally malicious) unterminated input has the potential to go off reading some other process's data, which opens up possible attack vectors, or the potential to cause unexpected page faults. strnlen() with one greater than the true buffer size, with the one extra memory read that it implies, has the same potential.
- adrian_b 4y agoNo, strnlen with any given length does not have the potential of reading anything that it should not read, like it is true for strlen. The length argument of strnlen is under the control of the kernel writer, not under the control of whoever provides the source string. The new strscpy function can also read anything, if the kernel writer allocates a destination buffer long enough, there is no difference between strscpy and strnlen, from the security POV. What they read is determined by the length of the destination buffer. Because the destination buffer must have an extra byte for the null terminating byte, strnlen must be called with the size of the destination buffer as argument, but if it returns that size, that signals an error, and then a number of bytes that is one less than the return value must be copied from the source (and a null byte must always be written after whatever is copied by memcpy). The kernel function strscpy is exactly equivalent with using correctly strnlen and memcpy. While strscpy encapsulates that behavior, so it is more convenient, anyone who wants to use strscpy in a user C program must define a strscpy macro or function, using strnlen and memcpy, which are standard functions.
- JdeBP 4y agoThe length given to strnlen() is, as you yourself said, greater than the size of the actual buffer in order to detect an oversize source. So strnlen() has the potential to access the character beyond the end of the array, checking it for NUL, incurring page faults and whatnot.
- kevin_thibedeau 4y ago*printf()s are slow.
- barbegal 4y agoPrintfs can be slow but their performance varies by implementation and may have no meaningful performance implications in many cases.
- ranger_danger 4y agoNot even close to accurate. I'm not aware of any large C library with a string copy function that guarantees a NULL-terminated result in all possible cases.
- morelisp 4y agoI mean, this ask is technically impossible since you may specify zero length to any of them. At that point signalling an error is the only thing it can do.