User: Password:
Subscribe / Log in / New account

strncpy() history

strncpy() history

Posted Jul 19, 2012 3:49 UTC (Thu) by tialaramex (subscriber, #21167)
Parent article: The ups and downs of strlcpy()

I was led to believe that strncpy() is the way it is not because the developers were trying to "fix" strcpy() to be secure (for which it's a terrible design) but because they wanted to truncate strings in fixed-width buffers that aren't themselves terminated anyway. Writing an "extra" NUL byte would be either wasteful or actively disastrous depending on whether it fitted inside the fixed width buffer or destroyed the next byte after it.

Such structures hardly exist at all today, but were very common back when we had things like record-oriented file operations and people worried about "wasting space" with the redundant century fields of a date...

(Log in to post comments)

strncpy() history

Posted Jul 19, 2012 5:40 UTC (Thu) by akanaber (subscriber, #23265) [Link]

Yes, that's why strncpy pads out the rest of the destination with NULs if strlen(src) < n
It's not terribly well named, it's really a function for converting between C-style null-terminated strings (src) and fixed-length records (dst). As you say it would be an insane design for a "safer strcpy", and as the article mentioned people who try to use it that way just introduce a different security hole.

strncpy() history

Posted Jul 19, 2012 12:33 UTC (Thu) by Yorick (subscriber, #19241) [Link]

I agree that strncpy() is badly named, and that this has led people to misunderstand its function and purpose. It is still useful for (mostly legacy) wire protocols and on-disk formats where, in addition to the fixed record size, the null byte padding is important (in order not to leak any information).

By the way, strncpy() does not seem to have an obvious inverse in the C library. Perhaps sscanf can be used, but it feels a little hacky and not what I would use in code that needs to go fast.

strncpy() history

Posted Jul 19, 2012 14:04 UTC (Thu) by danscox (subscriber, #4125) [Link]

The original reason for strncpy() was when directory names were limited to 14 chars. The other two bytes contained the inode number. For that particular case, strncpy() worked quite well. Yes, I've been at this for 'way too long now ;-).

strncpy() history

Posted Jul 19, 2012 19:21 UTC (Thu) by smoogen (subscriber, #97) [Link]

Dear lord.. that sentence led back to flashbacks from the 80's. Thanks.

strncpy() history

Posted May 25, 2017 1:36 UTC (Thu) by rlhamil (guest, #6472) [Link]

I thought that was the case too (14 character filenames in a directory entry only null-terminated if shorter than that), but looking through the v7 code, I didn't really see much in the way of examples of that, certainly not in the kernel. Here's everything I found (this is running on v7 on an emulated PDP-11 that is so much faster than the real thing that it reminds me how painfully slow they were by comparison):

unixv7# time find /usr/src /usr/sys -type f -name '*.[ch]' -exec grep strncpy /dev/null {} \;
/usr/src/libc/gen/strncpy.c:strncpy(s1, s2, n)
/usr/src/cmd/crypt.c: strncpy(buf, pw, 8);
/usr/src/cmd/ed.c: strncpy(buf, keyp, 8);
/usr/src/cmd/login.c:#define SCPYN(a, b) strncpy(a, b, sizeof(a))
/usr/src/cmd/mkdir.c: strncpy(pname, d, slash);
/usr/src/cmd/atrun.c: strncpy(file, dirent.d_name, DIRSIZ);
/usr/src/cmd/xsend/lib.c: strncpy(buf, s, 10);
/usr/src/cmd/ranlib.c: strncpy(firstname, arp.ar_name, 14);

real 7.0
user 2.0
sys 4.5

Without looking further, three appear to deal with pathname components, three deal with other things, one is a macro (turns out it was for a not-necessarily-terminated utmp.ut_name field), and one is the definition of strlcpy.

Copyright © 2017, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds