Date: Sat, 12 May 2001 17:05:44 +0300 From: Valentin Nechayev <netch@iv.nn.kiev.ua> To: Daniel Hemmerich <dan@BSDpro.com> Cc: freebsd-hackers@FreeBSD.ORG Subject: Re: adding a new function to libc Message-ID: <20010512170544.A343@iv.nn.kiev.ua> In-Reply-To: <01051202104500.95296@blackhole.BSDpro.com>; from dan@BSDpro.com on Sat, May 12, 2001 at 02:10:45AM -0400 References: <01051202104500.95296@blackhole.BSDpro.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Hello Daniel Hemmerich! Sat, May 12, 2001 at 02:10:45, dan (Daniel Hemmerich) wrote about "adding a new function to libc": > Any comments, suggestions, swears concerning adding a new function, > strndup(), to libc? > > So that instead of permitting it to attempt to allocate a large chunk of > memory, it is possible to give it a max length. Really, one should not use C-style null-terminated strings except situations where they are nesessary (e.g. kernel interface) because they all are too longfied nightmare, due to brain-damaged interface and high inefficiency. Recent libc changes - adding strlcpy() and strlcat() - were motivated AFAIU with well-grounded fear to find *selves in BugTraq top list of buggy platforms, and with aspiration to get rid of K&R crap - strcpy(), etc. (There is no such object as "unlimited string buffer"; there are "limited buffer" and "NUL-terminated constant string". strcpy() was designed to work with wrong "unlimited string buffer" concept and hence it must die. The same for its sisters such as strncat().) strndup(), in any of common-possible interpretations, is danger because caller cannot get info whether source string were longer (and copy is cut) or not. You can use such cutting actively in rare cases, e.g. debugging printing, but for sensitive work such _silent_ cutting can produce only bugs, not any useful thing. I cannot see any reason to include such danger function to libc. The most concrete factor is that your code is buggy because if source string is longer than max_len, destination string is not terminated with NUL properly. And it is inefficient: there is no need to waste processor time and cache cells to read unuseful data in strlen(). Hence, I'll think the better implementation is char* strndup( const char* src, size_t max_len ) { size_t len = strnlen( src, max_len ); char* ret = malloc( len + 1 ); if( ret ) { strncpy( ret, src, len ); ret[ len ] = 0; } return ret; } Here strnlen() is used which is non-standard but I saw it in ~4 quite different projects (e.g. Linux kernel) with identical interface and result value; a variant of implementation follows: /* This is candidate to have optimized assembler variant */ size_t strnlen( const char* src, size_t max ) { size_t n; while( n < max && *src != '\0' ) n++; return n; } > char * > strndup(str, max_len) > const char *str; > size_t max_len; > { > size_t len; > char *copy; > > len = strlen(str) + 1; > if (len > max_len) > len = max_len; > if ((copy = malloc(len)) == NULL) > return (NULL); > memcpy(copy, str, len); > return (copy); > } > > -- > Daniel Hemmerich > dan@BSDpro.com > > To Unsubscribe: send mail to majordomo@FreeBSD.org > with "unsubscribe freebsd-hackers" in the body of the message /netch To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010512170544.A343>