X-Originating-IP: [204.39.230.222] From: "David F" To: djgpp-workers AT delorie DOT com Subject: Re: RESEND: strlcat, strlcpy [PATCH] Date: Thu, 09 Jan 2003 00:28:20 +0000 Mime-Version: 1.0 Content-Type: text/plain; format=flowed Message-ID: X-OriginalArrivalTime: 09 Jan 2003 00:28:20.0829 (UTC) FILETIME=[033F28D0:01C2B776] Reply-To: djgpp-workers AT delorie DOT com Hello, There are a couple of omissions in the original paper. The specifications for both strlcpy and strlcat fail to consider the case where the buffers overlap. IMO, this is a minor issue. I figure most people would assume they handle such cases the same as strcpy and strcat, which is to say they don't handle such cases. So something along the lines of the following sentence should be added to their specification: "If copying takes place between objects that overlap, the behavior is undefined." Were they to be implemented in C99, their pointer arguments would most likely be restrict qualified. The second omission concerns an unconsidered case with regard to the input to strlcat. The original paper fails to consider the case when a NUL character is not found within the destination buffer. This case is strange to say the least and almost certainly represents a bug in the calling code, however, I think the behavior of strlcat in such a case should be defined. Particularly, I think strlcat should not read past the end of the buffer. I believe that in such cases the buffer should remain unmodified and strlcat's return value should be the sum of the specified buffer length and the length of the would-be concatenated string. That is how the current OpenBSD implementation handles this case. If you check the RCS log for OpenBSD's strlcat.c you will see that someone submitted a patch that would read past the end of the buffer until it found a NUL. The OpenBSD maintainers committed the patch, though better of it, and backed-out the patch a few hours latter. It's worth noting that the implementation proposed for inclusion in djgpp's libc will read past the end of the buffer. Personally, I like the below-included implementations. I believe them to be correct, they have no dependencies, and I think any modern compiler should be able to generate reasonably decent code from them (I could be wrong though; on any or all counts). Inclusion in a libc (and one that will only be compiled with gcc, at that) was not one of my goals when I wrote them, however. DJGPP was one of my first introductions to Free Software, and I am grateful for the effort you guys put into it. Cheers I hereby disclaim any copyright interest in the following code. size_t strlcpy(char *dest, const char *src, size_t count) { const char *p = src; if (count > 0) { while(--count && *p) *dest++ = *p++; *dest = '\0'; } for (; *p; ++p); return p - src; } size_t strlcat(char *dest, const char *src, size_t count) { char *p = dest; const char *s; while (count && *p) { ++p; --count; } if (count > 0) { while(--count && *src) *p++ = *src++; *p = '\0'; } if (!*src) { return p - dest; } else { s = src; do { ++src; } while (*src); return (p - dest) + (src - s); } } _________________________________________________________________ Add photos to your e-mail with MSN 8. Get 2 months FREE*. http://join.msn.com/?page=features/featuredemail