2

It's not too hard to demonstrate that strcpy on overlapped source and destination addresses fails on some platforms, either producing incorrect results or trapping (the latter with some negative random offsets on Linux/amd64).

I'd instrumented a strcpy wrapper function for our codebase with an debug-build assertions that check for such overlapped copies, and have received a number of internal development requests to weaken this assertion checking so that it only raises an abortion for non-zero overlaps.

I've been hesitant to do so, based on my read of the strcpy documentation since I'd assume that equal source and destinations would count as overlapped. Is overlapped defined explicitly in the C++ standard (or C), and does this also include equality?

I suspect many vendor strcpy implementations special case this despite the freedom the standard allows to have this be undefined behavior. Are there any platform/hardware combinations where such an equal copy is known to fail?

person the human
  • 345
  • 4
  • 15
Peeter Joot
  • 7,848
  • 7
  • 48
  • 82

2 Answers2

0

Since you are using C++, the question is really, why are you not using std::string. strcpy is notoriously unsafe (as are it's cousins strcpy_s and strncpy, although they are mildly safer than strcpy).

If you attempt to copy from a source to a destination that are the same, at best you will get no change.

Zac Howland
  • 15,777
  • 1
  • 26
  • 42
  • 2
    Only mildly safer: `strncpy` is about as evil as a size-limited string copying function can be and still be a size-limiting string copy function: [*"If count is reached before the entire string src was copied, the resulting character array is not null-terminated. If, after copying the terminating null character from src, count is not reached, additional null characters are written to dest until the total of count characters have been written."*](http://en.cppreference.com/w/cpp/string/byte/strncpy) – Yakk - Adam Nevraumont Sep 10 '13 at 19:56
  • The codebase contains millions of lines of legacy code. A global change to std::string is not feasible. – Peeter Joot Sep 10 '13 at 20:12
  • 1
    @PeeterJoot: Your best bet is then to wrap any calls to `strcpy`/`strncpy` with checks to make sure the buffers do not overlap, are properly null-terminated, and have the appropriate sizes. And work on a proposal to re-write the legacy code to bring it up to date. If you have that much technical debt now, it will only get worse until the system is utter and complete crap (from both a development and a user perspective). – Zac Howland Sep 10 '13 at 20:14
0

If you found yourself a better documentation website for C functions, you'd see this signature:

char *strcpy(char *restrict s1, const char *restrict s2);

restrict in this case indicates that the caller promises that the two buffers in question do not overlap.

We can further search for the meaning of restrict as of C99, and find this wikipedia page:

It says that for the lifetime of the pointer, only it or a value directly derived from it (such as pointer + 1) will be used to access the object to which it points.

which is pretty clear that identical pointers are not allowed. If it happens to work on your system, there is no reason for you to think it will work in the next iteration of the compiler, library, or on new hardware.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • Question is tagged C++, and C++ does not have _restrict_. – MSalters Sep 11 '13 at 11:16
  • @msalters C++ tends to refer to C for the behavior of C standard lib functions. – Yakk - Adam Nevraumont Sep 11 '13 at 12:29
  • Of course, but C++ can't refer to the C behavior of `restrict`. In particular, C++ includes only the C _library_, and `restrict` is not a library feature. – MSalters Sep 11 '13 at 13:14
  • @MSalters You are calling the same function, with pointers that are going to be C-compatible. If C executes undefined behavior if you fail to obey the C restriction of `restrict`, what will the same function called with code that disobeys the C definition of `restrict` do when called from C++? Hmm. – Yakk - Adam Nevraumont Sep 11 '13 at 14:26
  • 4
    In C++11, 17.2 explicitly states that the semantics of C `restrict` do not matter in C++. So, unless there are other restrictions (such as the non-overlapping requirement of `strcpy`), code that is UB in C99 may be well-defined in C++11. – MSalters Sep 12 '13 at 07:09