Winner of the 2015 Underhanded C Contest Announced (underhanded-c.org) 48
Xcott Craver writes: The Underhanded C contest results have now been announced. This time the contest challenge was to cause a false match in a nuclear inspection scenario, allowing a country to remove fissile material from a warhead without being noticed. The winner receives $1000 from the Nuclear Threat Initiative.
Do these programs compile (Score:2)
with -Wall -Werror ?
Re:Do these programs compile (Score:5, Funny)
Does any program compile with -Wall -Werror?
Re:Do these programs compile (Score:5, Insightful)
yes? mine do. Always.
if there's a warning you fix it. Or if it's unfixable you suppress that specific warning.
Re:Do these programs compile (Score:5, Insightful)
Some of the "warning" -Wall checks and calls out are asinine. There not worth the time to "fix" just to make the compiler happy.
I cannot remember a concrete, very specific case from ages past where this was true. But in general, and after seeing a ton of code, if you start from the beginning with -Wall -Werror and don't let that shit go, it goes a long way towards maintainability.
Additionally, the moment you let that discipline go, things begin to go to shit. And before you know it, you have your compilation logs fulled with warnings that you cannot turn off because of the off change one of them might be relevant, and no way to go back and clean that shit up because the technical debt is too huge.
I hate working with projects were -Wall -Werror is not the norm for the bulk of source code. In the general case, warnings are latent errors and you might as well squash them without mercy before the creep out of your control.
Re: (Score:1)
I believe the submission is also something that can be statically analysed though. It's converting to a pointer of a different type without a cast. It's still a crafty entry but very easily detected. Perhaps there is a cast not shown because of the excerpt.
Re:Do these programs compile (Score:5, Informative)
Hi,
In the winning entry there is no cast or "conversion" per se. It has one C file that calls a function and another C file that implements the function, with a mismatch between the types of the call and the implementation. Neither file by itself is performing any conversion or doing something wrong that can be caught by static analysis; the bug is caused by a mismatch between the code in two object files. This would only be caught by a tool that would examine the two files together, but it would not be caught by the compilation of either part.
We've actually seen a number of past entries that used this same basic trick to mismatch a call and an implementation. A previous winning entry managed to redefine the time() function as time_t time(void) instead of time_t time(time_t *ptr), avoiding a compiler warning by using the extern keyword. That's a neat trick because barely anyone uses the argument to time(), and after writing t=time(NULL) hundreds of times, it's easy to completely miss a call like t=time(). This caused a call to time() with the wrong number of arguments, so that another variable on the stack was used to hilarious effect.
Re: (Score:2)
Some of the "warning" -Wall checks and calls out are asinine...
I cannot remember a concrete, very specific case from ages past where this was true.
If you are using the Microsoft compiler, there are rather a lot of warnings along the lines of "I see that you are using a POSIX standard routine. You really should instead consider using our incompatible variant of it (incidentally tying your software to our platform) because F.U.D. Woggity boogity!"
In C++ template programming I also have started seeing a rather lot of "unreachable code" warnings due to code that will never be executed for one specific instantiation of a more generalized template. You co
Re: (Score:2, Insightful)
Some of the "warning" -Wall checks and calls out are asinine. There not worth the time to "fix" just to make the compiler happy.
Dude, when the folks who wrote the compiler that you're using to turn your source code into a runnable program took the time to do extra work to warn you that your seemingly-correct source code does something dodgy, you'd probably be best served to listen to them.
Re: (Score:1)
> Some of the "warning" -Wall checks and calls out are asinine.
[citation needed]
Besides, last time I checked, [anonymous coward] ain't a compiler expert. I *must* know.
-Wall yes, -Larry -Wall for obfuscation (Score:5, Funny)
Yes, -Wall is good way to find code smells.
For obfuscated code, I suggest -Larry -Wall.
Re: (Score:2, Interesting)
Re: (Score:2)
Re: (Score:2)
Hm, compile? Perhaps!
Does it run, too?
Linus Akesson? (Score:4, Interesting)
Re:Linus Akesson? (Score:5, Informative)
Re: (Score:2)
Re: (Score:2)
Wow ... (Score:2)
That's a highly specific thing ... who funded this again? :-P
Re: (Score:2)
The Nuclear Threat Initiative [nti.org].
This year's challenge (detailed below) is a real-world problem in nuclear verification, sponsored by and designed in partnership with the Nuclear Threat Initiative (http://www.nti.org/), a nonprofit, nonpartisan organization working to reduce the threat of nuclear, chemical and biological weapons.
Re: (Score:3)
Fixable - Easily (Score:1)
Do not use common function names when defining new function. This would be caught simply by insisting that the function is already named, and thus being sent back the the programmer to rename it something else.
Re: (Score:1)
Re: (Score:2)
This header file defines float_t as double precision, although by default math.h defines float_t as single precision.
Sorry. Technically float_t is a type, and defined as single precision. double_t is the correct type for double float
Regardless, redefining the float_t to being double is the problem, when it is already defined as something else. Sending back for a fix would solve the problem, rather than redefining what float_t means. Of course, you can remain pendantic and not get the point I was making. It is solvable, by sending the code back for revision, to remove the problematic re-defining of the type. In this case,
Re:Fixable - Easily (Score:4, Interesting)
It's not being redefined. Because of the way the C compiler works, it has different values at different points of compilation, but never does one definition get overwritten by another one. (Analogous to many wrong API based errors). The fact you would think it's checked against by the compiler makes this cleverer, because you'd expect the machine to throw a warning if it was actually redefined.
And float_t is supposed to define (at least as wide as a float) the commonly used float type in this environment. According to the given spec, the min float type was supposed to be a double. If that were consistently included in all files, it would have actually triggered errors if you ever used a regular float function. The problem was not enough redefining
Re: (Score:2)
My understanding if float_t means one thing here, and another thing there, then it isn't defined correctly. Standard Math.h files expect it one way, changing that in one place, but not passing that change on to every other possible place is problematic, and as a programmer SHOULD cause flags. Compilers don't care, as you stated.
It should have been flagged somewhere by someone or something. Because it wasn't, looked innocuous and has a potential for HUGE problems down the road. Just because something is allo
Volkswagen, is that you? (Score:5, Funny)
So winner's solution overrides standard type (Score:2)
typedef double float_t;
Nice solution, but I'm not sure it would not get detected with proper coding standard, peer reviews, and testing. But it would depend on a human factor. Plus compiler would likely give a warning for overriding a typedef.
Re:So winner's solution overrides standard type (Score:5, Interesting)
Hi,
I didn't mention it on the page, but the C file that #includes that header doesn't #include math.h, so there is no typedef overridden. A second C file #includes math.h without #including that header.
Re: (Score:3)
They carefully didn't include math.h (where float_t is normally defined) in the same file (but did elsewhere, to create the error.)
Even better, the floating point precision was defined in the spec as being a double. Therefore, the error looks benign. Certainly, a quick code review may thing it's actually setting the precision of the math library.
And, if discovered, it looks super-innocent.
This kind of solution is why I didn't enter. I had some ideas (all based around NaN poisoning), but knew that I didn't
Re: (Score:1)
I love this one. And, as you point out, it is the fact that it appears, if discovered, as a simple coding error that make it so elegant.
If it was caught, about all it would cause is a comment from your boss in the next one-on-one "Hey, dude, be more careful reviewing your code - spend more time if you need to" rather than a visit by the FBI or NSA (well, except maybe to hire you if they got wind of the bug and thought you were doing it "because you could", not "because you cared").
Re: (Score:3)
Exactly. The people commenting ITT that "it's easy to fix" or "the compiler should give a warning" or whatever miss the point entirely. This is sneaky use of a language feature.
How about an "Understandable C Contest"? (Score:5, Interesting)
I've enjoyed these over the years. My personal favorite was the "English to Pig Latin" translator whose source code looked like ASCII Art for a pig [github.com].
But really, if you can do stuff like that, you can do pretty much anything. So what's the point, really? Where's the challenge?
A much more interesting contest would be to write C code that's simple and understandable. Yes, I said it, simple and understandable and in C. There's a challenge to bend the minds of the world's greatest programmers.
Re:How about an "Understandable C Contest"? (Score:5, Informative)
You're thinking of the obfuscated C contest. That involves C code that operates correctly, but looks like junk (even under scrutiny). This is the underhanded C contest. This involves C code that looks correct (even under scrutiny), but operates like junk.
Re: (Score:2)
Not quite. The IOCCC entries are just supposed to be really misleading (iow: "obfuscated") in what they actually do. If you can't figure it out at all, that works. If you think you know what it does, but it does something else, that's even better.
The underhanded C contest just takes this principle, but applies it to security specifically.
Re: (Score:3)
To be fair, many entries boil down to precompiler shenanigans. Impressive, but not particularly interesting.
The underhanded C contest is, in my opinion, more interesting. Obfuscating something into a mess that is impossible to understand is relatively easy. Writing code that passes a decent examination of the source but is actually designed to fail in a very specific way is much harder.
Re: (Score:2)
so self-inflicted it isn't funny (Score:4, Interesting)
The stupid thing is that C++ name mangling [wikipedia.org] would already catch this problem at link time, and every modern C/C++ compiler already has code to support this, except that it's only activated for the much loved/unloved function overloading.
If GCC/clang in C mode generated mangled names into object files when compiling C programs (as purely informative records), the linker could diagnose this kind of problem as optional linkage errors—mighty darn useful, optional linkage errors.
This is a violation of the type system pure and simple, but one that doesn't compromise any specific compilation unit. That leaves the linker as the next line of defense, but like to keep our C linkers in dark boxes full of trust-me horse shit.
Re: (Score:2)
This is a violation of the type system pure and simple, but one that doesn't compromise any specific compilation unit. That leaves the linker as the next line of defense, but like to keep our C linkers in dark boxes full of trust-me horse shit.
For the most part linkers aren't supposed to be language-specific. Whatever language you use (it could indeed be C, but it could easily be something else) produces an object file in the OS's standard object file format, and the linker's job is to link various object files and libraries together into an executable.