Locksleyu
Locksleyu

Reputation: 5355

Is memcpy() unsafe in Mac OS X?

I know there is a great deal of discussion about how memcpy() is unsafe in the Windows/Microsoft world, but does that apply to Mac OS X code as well (Cocoa)? If so, what function should be used in Cocoa for maximum safety? memcpy_s() doesn't seem to be present on the platform.

Thanks.

Update: I realize speaking about memcpy() even in windows is sort of a gray area (see Memcpy() in secure programming?), but I am trying to discover whether this same exact discussion applies to Mac OS X or not. Just the fact that Mac OS X does't include a 'secure' version of memcpy() seems to imply Apple feels that things aren't that bad.

Upvotes: 0

Views: 4079

Answers (4)

JeremyP
JeremyP

Reputation: 86651

I'm not impressed by Microsoft's memcpy_s() because it is still up to the caller to supply the destination buffer size. Since the main thing that can go wrong with memcpy() (excepting if the source and destination buffers overlap) is caused by not knowing how big the destination buffer really is, is it not likely that the caller will put the wrong size for the destination in?

I suppose there is one class of errors it will help with exemplified by:

  char anArray[10]
  char* foo = anArray;
  memcpy_s(foo, sizeof foo, somewhereElse, 10);
  // or
  memcpy_s(foo, sizeof *foo, somewhereElse, 10);

However, both of these demonstrate a fundamental misunderstanding of C pointers and will likely not be the only problems with the code.

And what do you do if the destination is too small? Do you carry on with the truncated data? Do you put out an error message saying "Alert: programmer is an idiot"? No, it's better to know that your destination buffer is big enough before starting to do the copy.

Also, the link in the question talks about memcpy_s() having a null pointer check. Again, what are you going to do? Having the program crash is about all you can do sanely because, if a pointer you expected not to be null is null, you can't trust any part of your program's running environment. And on modern PC operating systems, the program will crash as soon as memcpy() attempts to dereference the null pointer.

Upvotes: 1

seabee
seabee

Reputation: 83

Buffer overflows (which is the security issue with memcpy, strcpy et al.) are OS-agnostic; essentially they're a problem inherent to the C language because it doesn't provide automatic bounds checking.

Used properly with due diligence, memcpy is safe; for example, if you validate the parameters yourself, or the sizes are known at compile-time. But everyone makes mistakes.

MS's approach in banning memcpy and using their own memcpy_s is to reduce bugs by forcing programmers to do the additional safety checks everywhere. You can write your own memcpy_s if you want; it's not hard to do, just implement the behaviour described on its MSDN page.

...seems to imply Apple feels that things aren't that bad.

The corollary is that Microsoft feels that things are that bad. However, what a company feels about a problem does not affect the existence of said problem, i.e. that not validating your inputs to memcpy is responsible for a class of vulnerabilities.

Upvotes: 2

j13r
j13r

Reputation: 2671

You should use memmove instead of memcpy when the memory areas can overlap.

They are not inherently unsafe if you program defensively and are aware of what they are actually doing.

Upvotes: 3

MByD
MByD

Reputation: 137362

It's quite new AFAIK, and not perfect, but GCC supplies a wrapper called __memcpy_chk which checks the size of the destination when possible, take a look here. The usage for it (from the same resource):

 #undef memcpy
 #define bos0(dest) __builtin_object_size (dest, 0)
 #define memcpy(dest, src, n) \
   __builtin___memcpy_chk (dest, src, n, bos0 (dest))

 char *volatile p;
 char buf[10];
 /* It is unknown what object p points to, so this is optimized
    into plain memcpy - no checking is possible.  */
 memcpy (p, "abcde", n);
 /* Destination is known and length too.  It is known at compile
    time there will be no overflow.  */
 memcpy (&buf[5], "abcde", 5);
 /* Destination is known, but the length is not known at compile time.
    This will result in __memcpy_chk call that can check for overflow
    at runtime.  */
 memcpy (&buf[5], "abcde", n);
 /* Destination is known and it is known at compile time there will
    be overflow.  There will be a warning and __memcpy_chk call that
    will abort the program at runtime.  */
 memcpy (&buf[6], "abcde", 5);

Upvotes: 2

Related Questions