Memcpy() and brethren, your days are numbered. At least in development shops that aspire to secure coding. Microsoft plans to formally banish the popular programming function that's been responsible for an untold number of security vulnerabilities over the years, not just in Windows but in countless other applications based on …
Can't fix C hacking
If the code was written properly, there'd already be bounds checking on the memcpy() count parameter. The real problem is that C can't associate sizes with pointers by itself. There's nothing to stop coders from using memcpy_s() with the wrong destination size, be it accidentally or intentionally. It will still crash the same way it did before.
Problem with the coders, not the language
Banning parts of a language because they could be dangerous or used unsafely is frankly ridiculous. It's a reason Java doesn't have real operator overloading and multiple inheritance. It's a weak argument people use to bash PHP (because it's easy to pick up and lots of idiots who shouldn't be programming in the first place use it).
C is a low level language, one step up from assembler. Some of us like C because of that. All this article tells me is that Microsoft (and others, not picking on MS specifically) employs a bunch of low-cost kids with no coding street-smarts to do the "dumb heavy work" making up the bulk of the code ... which in turn explains the crap code that pervades today's world of home computing.
It ain't t'language, lad, tis t'lad using t'language. (Or the t'Lady, with respect to Miss Bee.)
Let's see some evidence first..
AFAIK memcpy() is only one of the many ways in which you can hang any half-awake coder himself in C (some manage it when awake, but let's say charitable - I'm ignoring the chorus asking "why?").
Well done for thinking about security, boohoo for going straight to the press and trying to milk it instead of bloody DOING something for a change. Trust comes from casual "oh that? Yeah, we thought that was unsafe so we improved it" instead of trumpeting high and wide "look everyone, we bought a new padlock. Look how shiny it is, and how big¨" whilst still having a wooden backdoor with a simple latch only.
Do, don't talk. Show me. We've 20 years of marketing so pardon me for being cynical.
SDL turns out to be a list of banned APIs and a lot of useless rhetoric
Repeat after me, Banning APIs does not fix the underlying problem, Banning APIs does not fix the underlying problem, Banning APIs does not fix the underlying problem.
As someone who has had the chance to read a lot of proprietary code the problem is largely more or less what Kevin said-- theres nothing to stop you from using the wrong destination size. Only *one* team I've seen use the API correctly, everyone else does-- well exactly what ATL does in the following screen shot: http://www.innocence-lost.net/atl-generated.jpg.
Why is buffer overflow a problem?
Surely the operating system and the hardware can allocate space in such a way that data buffers are not executable and that the code of a program is not writeable. So why is this still a problem? Isn't the ability to mark memory blocks with flags controlling these things supposed to be a feature of proper operating systems and processors? I have vague memories of reading many years ago about the memory management features of mainframe computers that mention things like this. See also http://developer.amd.com/documentation/articles/pages/3312005143.aspx for instance.
Last time I checked Linus wrote a kernel, not a C library or a compiler.
memcpy() et al aren't "commands" , they're "functions"
Neither are they part of the "C" language - they are part of the "C" run-time support library, and these function calls aren't defined by the "C" language
They should go one better...
...and pop up a message box asking the user to confirm they want to copy the memory, and if they press OK then they should have to enter a captcha.
Seriously though, how is it supposed to make your code safer if you pass the size you think your destination buffer is? With memcpy, that size is implicitly greater or equal to the copy size and it's the caller's responsibility to make sure this is the case. Putting bounds checking into the copy function is ridiculous if you're responsible for passing the bounds yourself, and it goes against basic good design. I'm surprised they aren't passing the source buffer size too, just to be extra safe.
Also, what happened to the __restrict keyword? It's strangely absent from the memcpy_s function declaration.
wrong thing to ban
or its equivalent in any language until MS unequivocally states it will not try to own any of your code at a later date.
new size parameter ..err, what?
The memcpy i used so far has always had three parameters - destination, source AND number of bytes to copy.
How will adding *another* size indicator help avoid buffer overruns ? If the programmer was wrong in specifying a proper and safe bytes-to-copy parameter, are the chances really any larger to get it right in a second guess ;)
*note: memcpy is distince to the basic strcpy et co in this. Vanilla strcpy does *not* take a paramet specifying how much to copy, in the hope there will be a '\0' in the source before the destination buffer overflows. strncpy cures this.
In actual usage, however ...
int foo(char *inbuff)
char ams = "Ai'nt microsoft smrat?";
/* Specifying the source size twice makes us mostest secure */
memcpy_s(buff, sizeof(ams), ams, sizeof(ams));
/* This error logic you've seen before. */
if (memcpy_s(buff + 32, sizeof(buff), ams, sizeof(ams))) printf("Disk full");
/* Caller allocated inbuff based on available RAM; We *KNOW* it's big enough, but we don't know its exact size. This fix allows us to kill warnings.
NOTE: already tried memcpy_s(inbuff, sizeof(inbuff), ams, sizeof(ams)), it didn't work for some reason, probably another compiler bug */
memcpy_s(inbuff, 999999, ams, sizeof(ams));
Kevin is right - of course it will "work" in certain cases. In those cases it has probably been implemented thousands of times already (likely as a macro). But replacing the original memcpy() gives a misplaced and dangerous sense of security where none actually exists.
In order to understand the strcpy/strlcpy strcat/strlcat benefit, you first have to understand why and how it works, then you have to follow the rules. But buffers don't have rules, and slapping on another size parameter for security is like slapping a non-matching fake chrome exhaust pipe on your ricer to make it go faster and sound better. So, yeah, Linus and DrPepper probably will pick it up.
It's a start...
But I have to agree with Kevin that the core of the problem is using C, which checks nothing at runtime at not enough at compile time.
An alternative could be Cyclone (http://cyclone.thelanguage.org/), which shares a lot with C but has advanced features don't have and, more importantly, avoids many types of safety holes and bugs caused by C's lack of checking.
C# is also better than C in terms of safety and features. Microsoft is already using C# for a lot of things, but it is tied strongly to the .NET platform, so it can't be used for generic Windows programs or operating system modules. And for .NET, I would choose F# over C# any day.
This is insane
What's up with this trend of 'making life easier and safer'? If somebody wants to use safe alternatives - fine. But why do we need to _force_ people out of fast low-level stuff?
It's like 'yeah, you know, 99% of the programmers are idiots, really, who can't be trusted with dangerous stuff'. Only in ten years time there won't be anybody who can program your framoworks, libraries and OSes at all with that approach. Things are bad enough as it is, nine out of ten candidates whom I interview already do not know how computer works.
You can't stop a determined idiot
I note that openbsd did similar things by mandating use of their strlcpy and strlcat functions in the kernel instead of the usual strcpy and strcat, but still leave the old versions of the function available to ease application porting.
It helps that they have significant amounts of buffer overflow and stack smashing protection enabled by default in their version of gcc, significantly reducing the risks of an overflow.
I'd just like to say one thing.
About. Fucking. Time.
You'd think by now they would have written an appropriate bullet-proof wrapper for the function. I'm frankly shocked they haven't already done this, and the fact that they haven't explains so much about the lack of quality of their products.
"It's a question worth asking"
No it isn't a question worth asking. It's entirely possible to use memcpy safely, just as it's entirely possible to use memcpy_s (etc) wrongly.
Does the author or the people making these suggestions have any experience of Bill's current family of _s "improvements"? They're rubbish.
Why should slightly changing the name and the calling sequence turn carp programmers and carp designs into safe programmers and safe designs?
Only a poor craftsman blames his tools, and programming is a craft not a science.
What a daft concept, what a daft article.
Hmmm what does Linus have to do with this?
He has the kernel... not the C library(glibc). And this sounds like part of the C library not the kernel...
Or do you mean not using it in the kernel?
Read the article mate (also why the ms hate?)
Its to do with security, nothing to do with crashes, basically saying its a lot harder to cause security issues with the new function so use that instead.
You cant rely on the compiler or new functions to make your code secure. The only way to make code secure is to really understand what you are doing. Replacing memcpy with memcpy_s is silly and only leads to a false sense of security.
Is this a joke?
Yeah, the FA is pretty clear it doesn't make the operation any safer - it's more about forcing the programmer to consider the destination buffer size.
Also, it's a nice way of saying "to achieve this certification, you must audit all your existing memcpy calls", in a verifiable way. Again, it's easily bypassed by
sed -i *.c s/memcpy\((.*), (.*), (.*)\)/memcpy_s(\1, \3, \2, \3)/
but if you're really that short-sighted, there's nothing that could help you :-).
They seem to be missing a trick though. You should also be looking to try and replace memcpy() with structure assignment. Most C programmers don't even realise you can do that.
Incidentally, C99 does have support for array _parameters_ with an associated size. I think the syntax is "char a[*]".
# pragma deprecated (The C Language)
memcpy() is already bounded
I don't get this at all... The problem with strcpy() which causes so many overflow vulnerabilities is that the amount copied depends on the unpredictable C-string length of 'src', but memcpy() has an explicit length. Allowing that length to be greater than the size of 'dest' is sheer stupidity, not just laziness, and memcpy_s() won't protect you from that.
But who in Microsoft other than kernel/driver folk (who ought to know better, and who will resent the redundant comparison) is working in pure C anyway?
If people use memcpy properly in the first place it wouldn't be a problem
This is evidently another MS error.
System time on their publicity machine must have been reset to April 1st.
The comment by Kevin McMurtie is quite correct, you'll still be able to break things in the same way as before by passing dodgy parameters to memcpy_s()
They could declare a structure which began with a pointer and which then held the length of the data in bytes. Passing the structure (overridden natch) to any function would work and they could keep a count of the size of the data the pointer was looking at using the other variable. That might help...
A more sensible step for MS to take might be simply to hire programmers who knew how to use pointers. Oh, and if their developer turn-around wasn't so high, they'd have developers who were more intimiate with the code which would mean less bugs (of any type) would slip through.
...it goes without saying (so I'll say it anyway) that if their OS was more than a patch fix on a bug fix on a pile of half-arsed cludges they'd get on better anyway. Isn't it about time they got rid of the biggest flaw in their code - the design (or lack of). I'm talking about things like the registry... it's a joke.
Extend, embrace, extinguish...
I assume that MS have at least *heard* of K&R? Perhaps they'll be banishing the assembler next on the grounds that you can do anything...
Hopefully, #define _CRT_SECURE_NO_DEPRECATE will continue to work?
memcpy(dst, src, sizeof(*dst))
might help. Better to use abstract data types with dedicated copy functions. If done properly problems like this will be manifest at compile time, not run time.
Who does unchecked memcpys?
Oh yeah, Microsoft programmers...
How will an extra parameter help ?
The 3rd parameter is the number of bytes that you want to copy, so having another size ... what does it add ?
they're thinking ahead
@kevin: well at least they're trying something. its better than doing nothing don't you think?
Last time I looked, memcpy has a length parameter, unlike strcpy. Admittedly it's obscured by the size_t so there's a bit of brain work required to convert to bytes for real buffer size, but it's there. I assume the new function has an explicit check (i.e. slower) to accomplish the same thing at runtime but can still be broken by a programming error in specifying buffer size.
"The command is already supported in Microsoft's Visual C++, but according to Ullrich, native support doesn't yet seem to be available in the GCC compiler."
What's it got to do with the compiler? memcpy and friends are in glibc.
If you don't want people to call stuff insecurely, you need to train them to go about development in a considered manner. Just passing the destination size is not good enough to prevent buffer overflows, as it still relies on the programmer passing the right size.
If people aren't willing or able to think about stuff at that level, then they're better off using a higher-level language that would provide more safety anyway.
"Its drawback comes when the source to be copied contains more bytes than its destination, creating overflows that present attackers with opportunities to ...."
Hmmm,,, I think that's the symptom, rather than the cause.
There's nothing wrong with memcpy(). It reads a word from a source, and writes it to a destination, decrements a counter, and continues if the counter !=0
In other words, it does what it is supposed to do. The problem is that programmer did not bounds check before the memcpy was executed.
A simple if block around the memcpy is all that's needed.
memcpy ain't the only way of writing to memory
If you want to trash some memory, C provides endless ways of doing so. Anyone who thinks banning memcpy() will solve their security problems is fooling themselves.
What I don't see can't harm me
And what do they imagine is happening inside the code that they're too detached from the detail to know about?
Bulk memory shifting!, and you'd better be doing it with memcpy that uses the correct processor instructions because doing it in a loop is slow and crappy and incompetent and no more secure.
This is what AMD sued Intel for making their memcpy slow, and why processors have instructions built in to do it:
Code is like sausage, if your sausage is crap it's better to not know what's in it, and kid yourself it's grade A meat. Redmond produce a lot of this kind of sausage.
On the other hand the best sausage comes from the people who know what the pig that went into it had for breakfast.
I know that Steve refers to Steve Jobs of Apple and Linus refers to Linus Torvalds of Linux. Who does Larry refer to?
Re: Can't fix C hacking
I guess you didn't actually read the blog (or, maybe you did and are trying to look clever!)
From the blog:
"Of course, you can easily make a call to memcpy_s() insecure by getting the buffer sizes wrong. The following code is no better than memcpy():
You’ve been warned!"
"notoriously dangerous C commands"
Perhaps that should read "Notoriously dangerous stdio function library calls."
IIRC there are safer more restricted versions of memcpy which have safety built in. They are also part of the stdio library.
But maybe using them would demand too much thinking time when a release date is looming.
I'd love to see some stats on this in live code, like Windows for example. And how many of those could actually be banished by a replacement macro IE where the unlimited nature of this function is not actually necessary.
Thumbs up as better late than never.
You know what will happen...
What, my code doesn't complie? Hmm....
#define memcpy(dst, src, sz) memcpy_s(dst, sz, src, sz)
This is insane
Anyone clueful will already be checking the amount you're copying (the "count" parameter to memcpy()) fits in the destination buffer before making the call. So there is no advantage to these new functions.
Similarly for many of the other functions which they've already "deprecated".
This is just another Microsoft attempt to fragment the C and C++ languages, so people writing for Windows write in Microsoft-only "safe C" rather than real portable C. This makes it harder for people to write cross-platform applications, or to port their apps from Windows to Linux/Mac. And they get to spin it as "Microsoft caring about security!" too.
..we wouldn't want people learning to program properly would we.
This seems fairly pointless. The reason strcpy is dangerous is that the number of bytes which it attempts to copy, is not specified by the calling function at all - rather it is determined by the contents of the copied memory. Whereas memcpy always copies exactly the number of bytes that the calling function anticipates. I'm not sure there are many cases in which this will crash where memcpy_s would have helped?
I get memcpy_s but wtf use is fopen_s? That function doesn't write to the string buffer.
Bored of that VC warning about this stuff. Esp. with clients that *insist* that warnings were always *actually* meant to be errors. Yay for breaking all legacy C code!
I'd have to agree, the destination argument is irrelevant.
The proposed M$ fix is not really that helpful as it both makes the code non-portable (completely by accident I'm sure) and doesn't make it any safer as the above poster explains.
A much better way is to arrange that your calls are truncated at the limit of the
destination buffer using the sizeof operator, hence allowing the compiler to "associate sizes with pointers".
It's portable, pure ANSI and works a treat.
my_func(FOO *dest, BAR *src)
the memcpy function already has a parameter to specify how many bytes to copy:
memcpy(void *dst, const void *src, size_t len);
Destination, Source, Length...
If you add a 4th parameter, people will just put the length parameter twice, so if the specified length is wrong then it's wrong.
Leave my C alone!
C is a beautiful, wonderful language that sorts the men from the boys and no mistaking.
Sure, there are other ways to get things done quicker, but when you absolutely, positively have to squeeze every last ounce of performance out of something, well, there's no other way to go (except assembly and maybe C++).
Yes, you can shoot yourself in the foot, or the head, with ease. But that's what makes the language so flexible. Take away my ability to treat everything as a piece of memory filled that I can stomp all over as I like and you take away some of my power to make things go fast.
Notjing to do with C
I agree with that. memcpy can be called from within even VB. Its an adjunct.
Anyhow, its stupid to ban these things. More annoyance and intrusive "warnings" from MS who regard us as if we're all slightly backward children who can't be trusted with sharp things.
Except sizeof( dest ) in your example would equal sizeof( FOO* ), and not sizeof( FOO ). So maybe you really meant sizeof( *dest ).
And even when you get that right, if sizeof( FOO ) is greater than sizeof( BAR ) you'll be reading off the end of your source which could still crash if your source is located towards the end of your currently mapped address space.
So portable (check), pure ANSI (check), poorly thought though (check), bugged implemented (check), and about as safe as a cross-channel ferry made from tissue paper. Great, let's ship it before anyone in QA hits that edge case and notices.
The only real solution to real code stability and security is to stop using insecure languages and ensure people you employ are competent enough to fully understand the implications of *every* line of code they write.
Next step, ban pointers
There comes a point, if you are having to curtail programmers from doing something potentially damaging, where you have to consider that you are perhaps using the wrong programming language, or the wrong programmers, or both.
That said, this isn't a bug or problem with C itself but in the libarary. Even then it's not really a bug or problem, only when it's used improperly does the issue arise.
C allows plenty of damage to be done and it amazes me that it has gained such widespread acceptance. It is used in many circumstances where programmers would be better off using something else. Industry only has itself to blame for using the wrong tools for the job.
- Product Round-up Smartwatch face off: Pebble, MetaWatch and new hi-tech timepieces
- Geek's Guide to Britain BT Tower is just a relic? Wrong: It relays 18,000hrs of telly daily
- Geek's Guide to Britain The bunker at the end of the world - in Essex
- Review: Sony Xperia SP
- FLABBER-JASTED: It's 'jif', NOT '.gif', says man who should know