3

I read about the heartbleed exploit and that is was mistake with memcpy.

void * memcpy( void * dest, const void *src, size_t len );

A proper call to memcpy can look like this

int a[4711] [4711];
 int b[4711] [4711];
/* initialize a */
(void) memcpy( &b [0] [0], &a [0] [0], sizeof( a ) );

But why the third parameter, when would that be different from the size of the src? I've seen other examples where it's the dest size that is used, when should that be done?

jww
  • 97,681
  • 90
  • 411
  • 885
Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424
  • 2
    I think you mean `memcpy` not `memcopy`. – O. Jones Apr 12 '14 at 15:25
  • well, use cases of memcpy are much wider and much more complicated than create exact copies of two structures. Suppose you need to copy only a part of `a`. – user3159253 Apr 12 '14 at 15:27
  • 1
    also, C cannot look at the source of the calling function to guess which array and how much of it you actually wanted copied. – Deduplicator Apr 12 '14 at 15:29
  • 2
    Why the downvote? This is an important question with serious history, especially for folks who came up programming in Java or other memory managed languages. – O. Jones Apr 12 '14 at 15:39

3 Answers3

4

If you take a look a the the memcpy Man page, the third argument is the number of bytes that is copied from src to dst. So it doesn't matter if you use the size of src or size of dst. But you must ensure that the source and destination buffer sizes are at least equal or greater than the number of bytes copied. Otherwise, buffer overflow will occur.

tonga
  • 11,749
  • 25
  • 75
  • 96
2

In this case, the src and dest arrays are the same size so it does not matter which one you do sizeof on.

In general, if you use the dest size, then you guarantee that your writing does not cause a buffer overflow, which is typically (but not always) a more serious problem than reading past the end of src.

However, reading past the end of src can also be serious, as the Heartbeat case shows. To be robust, it's best to check both src and dest sizes and confirm that they are both what you expect them to be, before proceeding.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • There are many use cases for different size buffers, and truncation in one part can easily result in overflow elsewhere. Also, reading too much can result in all kinds of bad things happening, it just depends on the context. – Deduplicator Apr 12 '14 at 15:32
2

The third parameter of memcpy(dst,src,len) gives the number of bytes to copy.

If that number of bytes is bigger than the memory pointed to by either parameter, you are hosed. That's a technical term describing things like the Heartbleed bug, as well as quite a few other bugs I've had the delightful experience :-( of fixing.

If your software development mindset is oriented toward memory objects, the code pattern in your question is valid. For example, if you develop around the idea that you use memcpy() to make exact copies of entire objects, I suppose you would never use any third parameter besides sizeof(src).

But memcpy() is useful for many other sorts of operations, such as management of partial buffers, gathering disjointed streams of data into consecutive memory locations, and similar things.

It's also subject to misuse, and ordinarily has no checks against that. For example, there are probably tens of thousands of code snippets in the wild, many of them in embedded systems, that look something like this.

char [10] out;
char [] in = "Yo ho ho and a bottle of rum!";
...
memcpy (out, in, 1+ strlen(in));  /*don't do this or you're hosed!*/
O. Jones
  • 103,626
  • 17
  • 118
  • 172