summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormillert <millert@openbsd.org>2013-09-25 21:50:18 +0000
committermillert <millert@openbsd.org>2013-09-25 21:50:18 +0000
commite47a0b68bb6b60fa03ae58c21a5115b19cbc0f77 (patch)
tree52e8173189dcdcbacaa85c48eac3b0d59adb62de
parentAccording to POSIX, if the src and dst strings overlap, the behavior (diff)
downloadwireguard-openbsd-e47a0b68bb6b60fa03ae58c21a5115b19cbc0f77.tar.xz
wireguard-openbsd-e47a0b68bb6b60fa03ae58c21a5115b19cbc0f77.zip
Add examples to show why this is a terrible API. OK jmc@ henning@
-rw-r--r--lib/libc/string/stpcpy.361
1 files changed, 60 insertions, 1 deletions
diff --git a/lib/libc/string/stpcpy.3 b/lib/libc/string/stpcpy.3
index ea25610717d..cb74942afaf 100644
--- a/lib/libc/string/stpcpy.3
+++ b/lib/libc/string/stpcpy.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: stpcpy.3,v 1.4 2013/09/25 21:49:31 millert Exp $
+.\" $OpenBSD: stpcpy.3,v 1.5 2013/09/25 21:50:18 millert Exp $
.\"
.\" Copyright (c) 1990, 1991 The Regents of the University of California.
.\" All rights reserved.
@@ -103,7 +103,66 @@ if the length of
.Fa src
is greater than or equal to
.Fa len .
+.Sh EXAMPLES
+The most common use of
+.Fn stpcpy
+is to build up a string from multiple elements.
+The following example builds up a pathname from
+directory and file components using
+.Fn stpcpy :
+.Bd -literal -offset indent
+char *dir, *file, pname[PATH_MAX];
+
+\&...
+
+if (strlen(dir) + strlen("/") + strlen(file) >= sizeof(pname))
+ goto toolong;
+stpcpy(stpcpy(stpcpy(pname, dir), "/"), file);
+.Ed
+.Pp
+However, the size check required to avoid a buffer overflow is error
+prone since the check can become out of sync with the code that
+performs the copy.
+.Pp
+One might expect that
+.Fn stpncpy
+could be safely used instead, but it suffers from the same defects as
+.Fn strncpy .
+The example below using
+.Fn stpncpy
+is even more prone to error and will not detect when truncation occurs:
+.Bd -literal -offset indent
+char *dir, *file, pname[PATH_MAX];
+char *p1, *p2;
+
+\&...
+
+p1 = stpncpy(pname, dir, sizeof(pname) - 1);
+p2 = stpncpy(p1, "/", sizeof(pname) - 1 - (p1 - pname));
+stpncpy(p2, file, sizeof(pname) - 1 - (p2 - pname));
+pname[sizeof(pname) - 1] = '\e0';
+.Ed
+.Pp
+A safer (and simpler) approach is to use
+.Fn snprintf :
+.Bd -literal -offset indent
+char *dir, *file, pname[PATH_MAX];
+int len;
+
+\&...
+
+len = snprintf(pname, sizeof(pname), "%s/%s", dir, file);
+if (len >= sizeof(pname))
+ goto toolong;
+.Ed
+.Pp
+In most cases, it is better to use
+.Fn snprintf ,
+.Fn strlcpy ,
+or
+.Fn strlcat .
.Sh SEE ALSO
+.Xr snprintf 3 ,
.Xr strcpy 3 ,
.Xr strlcpy 3 ,
.Xr strncpy 3