From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe)
Newsgroups: comp.lang.c
Subject: Re: strcpy implementation question
Date: 27 Aug 92 06:56:37 GMT
Organization: Comp Sci, RMIT, Melbourne, Australia

In article <PINKAS.92Aug25163006@caraway.intel.com>, pinkas@caraway.intel.com (Israel Pinkas) writes:
> In article <14173@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
> 
> > There is a very basic problem which explains why strcpy() should touch
> > only strlen(source)+1 chars:
> >	 characters following the intended end of the source MAY NOT EXIST
> >	 characters following the intended end of the destination MAY NOT EXIST
> >	 characters following the intended end of the source may exist
> >	 AND YET NOT BE INITIALISED.
> 
> I wish people would read my posting.  I specifically detailed the fact that
> the strcpy routine in question only was used when the source AND
> destination had been allocated by the compiler and were of a known size AT
> COMPILE TIME.

I wish people would read charitably and not assume that the answer is
irrelevant to their question without thinking.

The point is _uniformity_.  Since strcpy() *can't* go too far in the
great majority of cases, it will only be confusing if it does something
different in this case.

When is the size of the source known at compile time?  Two cases:
(a) the source is a string literal (or is a pointer whose value is known
    by constant propagation to be a specific string literal)
(b) the code looks something like
	if (strlen(x) == 27) { /* don't change x */; strcpy(d, x); ...}

> The fact that the memory has not been initialized is irrelevant.  If the
> source didn't care about it, neither will the destination..

This is wrong.  It isn' the source or the destination that cares, it is
strcpy() that cares.  strcpy() MUST NOT READ any uninitialised memory
locations.

> > The traditional documentation for strcpy() said:
> >	 strcpy copies string s2 to s1,
> >     -->	stopping after the null character has been moved
> > X3J11 weren't in the business of breaking anything they didn't _have_ to
> > break, not if they could help it.
> 
> Man pages do not a spec make.

On the contrary, until X3J11 published the final standard, that *WAS*
the spec.  The spec for strcpy() _was_ (until the ANSI standard was
published) whatever the SVID said it was, and the SVID says
	char *strcpy(s, s2) char *s1, *s2;
	The function strcpy() copies string s2 to s1,
	stopping after the null character has been copied.
	The functions ... strcpy ... all alter s1.
	These functions do not check for overflow of the array pointed to by s1
	... Each function returns s1.

The spec _NOW_ is whatever X3J11 say it is (our copy of the standard _still_
hasn't arrived or I'd quote it).  But you can bet your ar-- that X3J11 didn't
_intend_ to change this.

Plauger & Brodie isn't the ANSI standard either (I'll start quoting that just
as soon as our copy arrives).  But they say:
	char *strcpy(char *s1, const char *s2)
	This function copies the string s2, including its terminating null
	character, to successive elements of the array of char whose first
	element has the address s1.  It returns s1.
You can be pretty sure that a whole lot of C programmers are going to take
that as gospel.

> I specifically asked people for a spec that states that the optimization is
> illegal or for pointers to code that is widely used that will be broken by
> this code.

Several people have posted examples like
	char buffer[3+1+3+1];
	strcpy(buffer+3+1, "bar");
	strcpy(buffer, "foo);
	buffer[3] = '.';
which ought to set buffer to |foo.bar\0|.

-- 
You can lie with statistics ... but not to a statistician.