[comp.bugs.2bsd] V1.21

bostic@OKEEFFE.BERKELEY.EDU (Keith Bostic) (01/07/88)

Subject: strncat is broken
Index: lib/libc/pdp/gen/strncat.s 2.10BSD

Description:
	strncat(3) doesn't truncate strings correctly.

Repeat-By:
	The following program demonstrates the bug.

	#include <stdio.h>
	#include <strings.h>
	main()
	{
		char *s = "This is a long string, but we'll truncate it at the comma";
		s[21] = '\0';
		printf("%s\n", s);
		strncat(s, "Arragh!!", 7);
		printf("%s\n", s);
	}

Fix:
	Apply the following patch.

*** strncat.s.orig	Wed Jan  6 11:41:24 1988
--- strncat.s	Wed Jan  6 11:41:34 1988
***************
*** 36,41 ****
--- 36,42 ----
  	movb	(r2)+,(r1)+	/ copy s2 to the end of s1 stopping at the
  	beq	3f		/   end of s2 or when n runs out ...
  	sob	r0,2b
+ 	clrb	(r1)
  3:
  	mov	(sp)+,r2	/ restore r2
  4:

jpn@teddy.UUCP (John P. Nelson) (01/08/88)

>Description:
>	strncat(3) doesn't truncate strings correctly.

Please don't "fix" this "bug".  It is DOCUMENTED to work this way.  If
the second string is longer than the size "n" supplied, then NO NULL
TERMINATER is appended.  It is your MISUSE of "strncat" at fault here!

I agree, it is a pain in the ass, but this is the way strncat has
always worked since the beginning of C!

casey@lll-crg.llnl.gov (Casey Leedom) (01/08/88)

In article <4557@teddy.UUCP> jpn@teddy.UUCP (John P. Nelson) writes:
>>Description:
>>	strncat(3) doesn't truncate strings correctly.
>
>Please don't "fix" this "bug".  It is DOCUMENTED to work this way.  If
>the second string is longer than the size "n" supplied, then NO NULL
>TERMINATER is appended.  It is your MISUSE of "strncat" at fault here!

  No, it is a bug.  I'm embarrassed as the writer of the routine to admit it.
The manual page says the following:

     Strcat appends a copy of string s2 to the end of string s1.
     Strncat copies at most n characters.  Both return a pointer
     to the null-terminated result.

Since the original string is already NUL terminated, appending n
characters from s2 to the end of s1 and then NUL terminating the result
can really be thought of as inserting n characters just before the NUL in
s1.  You'll also note that both the C and VAX assembler versions NUL
terminate the result when strlen(s2) > n.  (Though the C version does have
an error in it because it won't handle n==0 and really should stop
copying one character earlier (it copies a character and then has to
stomp on it with a NUL.))

Casey

rpw3@amdcad.AMD.COM (Rob Warnock) (01/08/88)

In article <4557@teddy.UUCP> you write:
+---------------
| >	strncat(3) doesn't truncate strings correctly.
| Please don't "fix" this "bug".  It is DOCUMENTED to work this way.  If
| the second string is longer than the size "n" supplied, then NO NULL
| TERMINATER is appended.  It is your MISUSE of "strncat" at fault here!
| I agree, it is a pain in the ass, but this is the way strncat has
| always worked since the beginning of C!
+---------------

Sorry, "jpn", Keith was right the first time. The posted fix was to "strncat",
NOT to "strncpy"! (Yeah, I had to look twice, myself...)

True, "strncpy(dest, src, n)" does (read "MUST") leave the string unterminated
if strlen(src) >= n, but "strncat(dest, src, n)" ALWAYS null-terminates (after
copying at most "n" bytes).

Better luck next time...   ;-}


Rob Warnock
Systems Architecture Consultant

UUCP:	  {amdcad,fortune,sun,attmail}!redwood!rpw3
ATTmail:  !rpw3
DDD:	  (415)572-2607
USPS:	  627 26th Ave, San Mateo, CA  94403