One trivial and silly real-world example: I'm currently working on a C codebase with a few developers in India. Sometime before I started the project, the American company I now work for contracted out a security audit of the code, and one of the obvious conclusions was that "safe string functions should be used" - strcpy() had been used to copy user input to statically sized buffers such that it was vulnerable to classic buffer overflows, all over the place. Requirement set, requirement followed - now strncpy() and strncmp() etc were used everywhere, but always either uselessly (25% of the time) or wrong and unsafe (75%). Most typical was to use the length of the source, calculated with strlen(). Now, I guess it was not specified "use strncpy() correctly, with the size of the destination". Failure of specification, right?
For what it's worth, the root of the problems on this particular project are that the original American lead dev was not that great and set some bad examples, which the outsourced devs copy diligently and industriously.
(But then again, it's not enough to say "this is clearly wrong, it will overflow if (expr)" - they tend to need explicit examples to copy. Sometimes they impress me by figuring the cause of a tricky bug. Sometimes they write smart but actually useless code, like using floats and log() to figure out how big a buffer is needed to print a uint16_t in decimal - 5 bytes will suffice, no float math needed. Sometimes they write 20 lines of code to calculate how long the string result of snprintf() will be, instead of using the size of the destination, right after I've lectured on what strncpy() is for. They often seem less thoughtful than a neural net. I've even seen "buf[strlen(buf)] = '\0'" - I just have no words sometimes.)