Microsoft's list of banned C functions
github.com
github.com
For example, you see memcpy() on Microsoft’s list. That doesn't mean that Microsoft simply “banned memcpy”, it means that Microsoft wants their developers to use an alternative function called memcpy_s(). The _s suffix means “secure”. These functions are defined in Annex K of the C standard, which is an optional part of the C standard. If you look at memcpy_s(), it may seem a bit weird:
errno_t memcpy_s( void *restrict dest, rsize_t destsz,
const void *restrict src, rsize_t count );
Note that this is more than plain bounds checking, and I believe it’s also intended to be used with static analysis tools to ensure that it’s being called correctly—and the API is designed to make static analysis tools easier to write!As far as I can tell, Microsoft is really the only major user of Annex K. There may be a couple other users, but Microsoft is the big one. Microsoft reportedly pushed for the inclusion of Annex K into the C standard, implemented it in their own C toolchain, and wrote a bunch of tooling to work with the Annex K functions inside their massive legacy C codebase.
You see, sometimes you have to do things a bit different if you have tons of legacy code and aren’t willing to spend the (prohibitively expensive) effort to rewrite it all with newer, safer techniques (use your imagination—like C++ or Rust). The _s Annex K functions are designed to replace the unsafe variants in a somewhat predictable, mechanical fashion so you can send a bunch of programmers into your legacy code base to fix security holes. And it does work.
Git is a much newer C code base, is much smaller than Microsoft’s C code, not as old, and doesn’t run in the kernel. In Git, you’d be expected to manipulate strings with strbuf (https://github.com/git/git/blob/master/strbuf.h) which is generally much safer and easier to use than the C stdlib. It’s just so much easier to make decisions like this in a new codebase like Git’s.
No, Microsoft's approach involves replacing the relevant functions with functions that are semantically different (and incompatible to) the Annex K functions.
[EDIT: In case anyone is wondering, the Annex K functions that Microsoft provides will compile error-free on a conforming implementation (function signatures are the same), but because they are incompatible with what each parameter means sometimes they will crash].
This is not really an unusual turn of events, and not something peculiar to Microsoft. Standards development is rarely “standards-first”. Instead, you implement your proposal, put it into use, and then go through the standards process. This is usually the way it should be done, and it’s how WHATWG did HTML5, it’s how Google did HTTP/2, etc.
After all, ISTR the interface remains the same for most (if not all) the Annex K functions.
Not completely their fault.
This and the other two bugs can be particularly nasty when doing something such as an arena allocator or any other means of user memory pools.
After an incredibly long slog on some particularly nasty corruption issues years ago I was only able to identify the problem by using ld preload and patching memcpy with some simple value and boundary checks for these three problems. Each of them was a source of the corruption.
In my mind a safer version for daily use wouldn't support the more problematic format options but maybe other people use them far more widely than me.
Please justify that claim. snprintf() limits itself to the specified buffer size (in the way safe from off-by-one errors) and always null-terminates. What more do you want?
Could you provide some source that corroborates this? Because my understanding is that this has no effect. It merely states something that is already true. That’s what I was hinting at with “possibly meaningless”.
Because all the countries who signed that treaty didn't move to the Berne Convention right away, you had to still reserve your copyright or else lose it in those countries.
The last holdout signed the Berne Convention in 2000, so it's no longer an issue.
* http://jdebp.uk./FGA/law-copyright-all-rights-reserved.html
I don’t think it’s an issue of whether it was rejected on principle, or because of its origin, I think that there just wasn’t enough interest in it. My feeling is that Annex K is not as useful without the right set of code review practices and static analysis tools. Many of the secure variants just take an extra size parameter—you would need some kind of assurance that the extra size parameter is somehow correct; without this assurance, the Annex K functions aren’t very useful. There’s not a great way to get that assurance without static analysis tools, as far as I know, because there are tons of unsafe ways to use the Annex K functions, like this:
// Don’t do this.
err = memcpy_s(dest, n, src, n);
If you’re just duplicating the “count” argument and pasting it in “destsz”, it will work but it won’t catch any of the errors that memcpy_s is designed to catch.0. http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm
That's exactly what annex k does. Detection of a runtime-constraint violation results in a call to a constraint handler; which handler can abort the process if you want it to.
> Note that it is assumed that a freestanding environment will additionally provide memcpy, memmove, memset, and memcmp implementations, as these are needed for efficient codegen for many programs.
GCC has effectively the same stipulation[1]:
> GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp.
The main thing I'm confused about is why you didn't get a linker error.
0. https://clang.llvm.org/docs/CommandGuide/clang.html#cmdoptio...
EFI isn't your usual Freestanding env. Your output is a dynamically linked PE2 (Windows) executable. The linker had spots for memcpy and others to be linked in Dynamically. But they were not. Whatever was there caused a hang in TianoCore UEFI. (Which would eventually reset due to the watchdog timer)
so does gcc, it's pretty much a requirement of the C standard. https://gcc.godbolt.org/z/aaE5hn
Why would the C standard mandate the presence of standard library functions in a freestanding environment? I always assumed compilers emitting calls to mem* functions were doing it because it was the easy solution just like linking to libgcc.
(Or with the Annex K variants -- memcpy_s(), memmove_s() -- if that floats your boat, and as this is Microsoft it surely does.)
You don't replace memcpy unless you do it right. The difference between systems with a bad or good memcpy is abysmal.