[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
library/1884: strlcat() should always NUL terminate dst, maybe
- To: gnats@openbsd.org
- Subject: library/1884: strlcat() should always NUL terminate dst, maybe
- From: gphilip2@qwest.net
- Date: Sat, 16 Jun 2001 20:24:01 -0700 (MST)
- Resent-Date: Sat, 16 Jun 2001 21:30:03 -0600 (MDT)
- Resent-From: gnats@cvs.openbsd.org (GNATS Management)
- Resent-Message-Id: <200106170330.f5H3U3a26288@cvs.openbsd.org>
- Resent-Reply-To: gnats@cvs.openbsd.org, gphilip2@qwest.net
- Resent-To: bugs@cvs.openbsd.org
>Number: 1884
>Category: library
>Synopsis: strlcat() should always NUL terminate dst, maybe
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bugs
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Jun 16 21:30:02 MDT 2001
>Last-Modified:
>Originator: Philip Guenther
>Organization:
net
>Release: current
>Environment:
System : OpenBSD 2.9
Architecture: OpenBSD.i386
Machine : i386
>Description:
As others have pointed out, if strlcat() is passed a dst
that isn't NUL terminated within the first siz bytes, then
something has obviously gone wrong already.
When I read the manpage to see what strlcat() does in this
case, it initially interpreted it as saying that strlcat()
and strlcpy() would *always* return with dst NUL terminated.
A look at the source showed otherwise, of course.
I would argue that it is more useful for strlcat() to provide
the invariant "siz == 0 || strlen(dst) < siz" than to leave
the string untouched in that case.
In a sense, I would take the decision from the 1.6-->1.7
patch on strlcat.c one step further: not only will strlcat()
not read or write beyond dst[siz-1], but it'll try to prevent
others from erroneously doing so.
>How-To-Repeat:
morgaine% cat foo.c
#include <stdio.h>
#include <string.h>
int main(void)
{ char buf[] = "foobar";
size_t len;
len = strlcat(buf,"baz",3);
printf("buf = '%s'\nlen = %u\n", buf, len);
return 0;
}
morgaine% cc foo.c && ./a.out
buf = 'foobar'
len = 6
morgaine%
>Fix:
This patch is against the main branch, not branch OPENBSD_2_9.
Index: strlcat.c
===================================================================
RCS file: /home/cvs/openbsd/src/lib/libc/string/strlcat.c,v
retrieving revision 1.8
diff -c -c -r1.8 strlcat.c
*** strlcat.c 2001/05/13 15:40:15 1.8
--- strlcat.c 2001/06/17 03:02:07
***************
*** 58,65 ****
dlen = d - dst;
n = siz - dlen;
! if (n == 0)
return(dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
--- 58,68 ----
dlen = d - dst;
n = siz - dlen;
! if (n == 0) {
! if (siz > 0)
! d[-1] = '\0';
return(dlen + strlen(s));
+ }
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
Index: strlcpy.3
===================================================================
RCS file: /home/cvs/openbsd/src/lib/libc/string/strlcpy.3,v
retrieving revision 1.12
diff -c -c -r1.12 strlcpy.3
*** strlcpy.3 2001/05/07 15:51:54 1.12
--- strlcpy.3 2001/06/17 02:55:25
***************
*** 135,141 ****
.Fa dst
is not a proper
.Dq C
! string).
The check exists to prevent potential security problems in incorrect code.
.Sh EXAMPLES
The following code fragment illustrates the simple case:
--- 135,146 ----
.Fa dst
is not a proper
.Dq C
! string). As long as
! .Fa size
! is not zero,
! .Fn strlcat
! will still NUL terminate
! .Fa dst .
The check exists to prevent potential security problems in incorrect code.
.Sh EXAMPLES
The following code fragment illustrates the simple case:
>Audit-Trail:
>Unformatted: