From owner-freebsd-hackers Thu Jul 15 17: 4:13 1999 Delivered-To: freebsd-hackers@freebsd.org Received: from dingo.cdrom.com (dingo.cdrom.com [204.216.28.145]) by hub.freebsd.org (Postfix) with ESMTP id ECE3914E2E for ; Thu, 15 Jul 1999 17:04:11 -0700 (PDT) (envelope-from mike@dingo.cdrom.com) Received: from dingo.cdrom.com (localhost.cdrom.com [127.0.0.1]) by dingo.cdrom.com (8.9.3/8.8.8) with ESMTP id QAA01894 for ; Thu, 15 Jul 1999 16:58:53 -0700 (PDT) (envelope-from mike@dingo.cdrom.com) Message-Id: <199907152358.QAA01894@dingo.cdrom.com> X-Mailer: exmh version 2.0.2 2/24/98 To: freebsd-hackers@FreeBSD.ORG Subject: Re: OpenBSD's strlcpy(3) and strlcat(3) In-reply-to: Your message of "Thu, 15 Jul 1999 17:38:16 MDT." Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Thu, 15 Jul 1999 16:58:52 -0700 From: Mike Smith Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG > On Thu, 15 Jul 1999, Mike Smith wrote: > > > Ugh. Take the first example in the paper; it rewrites as > > > > len = asprintf(&path, "%s/.foorc"); > > > > as opposed to > > > > strlcat(path, homedir, sizeof(path)); > > strlcat(path, "/", sizeof(path)); > > strlcat(path, ".foord", sizeof(path)); > > len = strlen(path); > > > > Yes, they're a better str*cat/cpy, but they're not the solution that > > they claim to be. > > I don't think that anyone has intended them to be anything other than a > better replacement for strcpy/strcat than strncpy/strncat (which they > certainly are). Sure, you could go around telling people "use snprintf > instead" or "use asprintf instead", but is that the issue at hand? In context, yes it is. The paper talks about dealing with the construction of composite strings into static buffers, and points out that there's a real problem when you hit the edge of the buffer (overflow, truncation, etc.) But they don't address the core of the problem, which is the use of a static buffer in the first place. This and other habitual programming style items are what's at the real core of the "C is an insecure language" argument; people are so used to these idiomatic programming techniques they refuse to look for better solutions to the larger problem. Going back to the example they gave, let's put it in context. You probably have something like this: { struct passwd *pw; char buf[MAXPATHLEN]; FILE *fp; pw = getpwuid(getuid()); strlcpy(buf, pw->dir, sizeof(buf)); strlcat(buf, "/.appname/", sizeof(buf)); strlcat(buf, conffilename, sizeof(buf)); if (strlen(buf) >= sizeof(buf)) return(error); fp = fopen(buf, "r"); ... That works, as long as MAXPATHLEN is actually long enough. In this particular case it will be (because fopen will fail otherwise), but there's no guarantee that you're going to know in advance. OTOH, here it is with asprintf: { struct passwd *pw; char *buf; FILE *fp; pw = getpwuid(getuid()); if (asprintf(&buf, "%s/.appname/%s", pw->dir, conffilename) == -1) return(error); fp = fopen(buf, "r"); free(buf); ... The latter has a few really clear advantages: - you can see what the string is meant to look like. - it doesn't matter how long any of the components are. - the constructed value is on the heap, so you can return it (just imagine how much nicer ctime() would be if it did this). -- \\ The mind's the standard \\ Mike Smith \\ of the man. \\ msmith@freebsd.org \\ -- Joseph Merrick \\ msmith@cdrom.com To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message