Chris Lalancette wrote: >> Clearly strncpy() is just unfit for purpose, and we should plan to banish >> it in favour of a virStrncpy impl that guarnetees to add the trailing \0. > > Yeah, true. Despite the ACKs from you and markmc, I decided not to commit this > yet. It's quite a theoretical bug (you'd have to have > /var/very/long/non-standard/paths/to/libvirt), so I don't think it's absolutely > critical right now. I'll convert the rest of the users, and possible come up > with a make syntax-check rule to prevent against future use. Sigh. Unfortunately, this is a difficult problem. I did some reading, and found that besides having the NULL termination problem, strncpy() is also very slow, so should be avoided. I then looked at doing an implementation of strlcpy(), but while it would prevent the buffer overflow, it can truncate the resulting string. This could lead to difficult detect errors later on. Note that both my original proposed patch for this problem plus many of current in-tree users of strncpy() suffer from this problem as well. Therefore, I think the way to go is probably to have a safe version of strcpy() which checks that the length of destination is sufficient to hold all of the source plus the \0. If not, it should return an error, and then the caller can decide what to do. Something like this: /** * virStrcpy * * A safe version of strcpy. The last parameter is the number of bytes * available in the destination string, *not* the number of bytes you want * to copy. If the destination is not large enough to hold all of the * src string, NULL is returned and no data is copied. If the destination * is large enough to hold all of the src, then the string is copied and * a pointer to the destination string is returned. */ char * virStrcpy(char *dest, const char *src, size_t destbytes) { int len; len = strlen(src) + 1; if (len > destbytes) return NULL; return memcpy(dest, src, len); } And usage would be: char foo[5]; virStrcpy(foo, "hello", sizeof(foo)); /* returns an error, foo is not large enough for hello\0 */ char bar[6]; virStrcpy(bar, "hello", sizeof(foo)); /* succeeds, foo is large enough for hello\0 */ A brief look through the current usage of strncpy() in libvirt shows that this would be a drop in replacement for most of the current users of strncpy(), and be safer as well. What do you think? -- Chris Lalancette -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list