
Results of the 2015 Underhanded C Contest - r4um
http://www.underhanded-c.org/#winner
======
makomk
There's an interesting subtlety mentioned in the author's explanation
[http://www.linusakesson.net/programming/underhanded/2015-spo...](http://www.linusakesson.net/programming/underhanded/2015-spoilers.pdf)
that doesn't seem to be mentioned here: the preprocessing had to be carefully
designed because the squashing also amplifies any residual noise, so if that
wasn't thoroughly removed the comparison would fail because it'd mostly be
comparing noise rather than signal. While the type confusion is the only
suspicious thing, the rest of the code did have to be crafted to make it work,
it's just that the other changes are reasonable and non-suspicious.

------
saucetenuto
I think this is my favorite Underhanded C submission ever. One simple
ambiguity, applied with breathtaking precision and effectiveness. Puts me in
mind of an old essay of Zed's: [http://zedshaw.com/archive/the-master-the-
expert-the-program...](http://zedshaw.com/archive/the-master-the-expert-the-
programmer/)

~~~
teddyh
From the essay:

> _In contrast there are masters in the martial arts who learned their art as
> a means of survival and became masters in a realistic and hostile
> environment. We don’t have anyone like this in the programming profession,
> or at least I haven’t met any._

Charles H. Moore springs to mind.

~~~
pavel_lishin
> _Charles H. Moore springs to mind._

Can you expand on this?

~~~
teddyh
Quote from
([http://www.ultratechnology.com/1xforth.htm](http://www.ultratechnology.com/1xforth.htm)):

“ _I wish I knew what to tell you that would lead you to write good Forth. I
can demonstrate. I have demonstrated in the past, ad nauseam, applications
where I can reduce the amount of code by 90% percent and in some cases 99%. It
can be done, but in a case by case basis. The general principle still eludes
me._ ”

------
blaze33
And if, like me, you didn't knew what this contest was about, the explanation
is one click away [1]:

"a competition that challenges coders to solve a simple data processing
problem by writing innocent-looking C code that is as readable, clear, and
seemingly trustworthy as possible, yet covertly implements a malicious
function."

[1]
[http://underhanded-c.org/_page_id_5.html](http://underhanded-c.org/_page_id_5.html)

------
userbinator
The winning entry reminds me of Linus (Torvalds)' viewpoint on typedefs:
[http://yarchive.net/comp/linux/typedefs.html](http://yarchive.net/comp/linux/typedefs.html)

Those for whom the name Linus _Åkesson_ is unfamiliar are highly encouraged to
visit his site at [http://www.linusakesson.net/](http://www.linusakesson.net/)
\--- he has a lot of other interesting articles on programming and the
demoscene.

~~~
kbart
_" if your typing speed is the main issue when you're coding, you're doing
something seriously wrong"_

So does he mean that programming/hacking is not about banging a keyboard as
fast as possible?/s I wish more people knew that.

~~~
gpvos
Most importantly, I wish more _managers_ knew that.

------
Kiro
Here's Linus in a completely different but awesome context:
[https://www.youtube.com/watch?v=m1pchpDD5EU](https://www.youtube.com/watch?v=m1pchpDD5EU)

------
asgfoi
I wonder how many of them would be caught using a very strict compiler flag
regime.

For the winner, perhaps the gcc flag, _-Wmissing-prototypes_ would catch it?

~~~
nkurz
No, that doesn't catch it because "float_t" is properly defined as a 'float'
by including <math.h>, instead of a 'double' in the local header. But I
thought you might be on to something with adding extra warnings, so I tried it
out on [http://gcc.godbolt.org](http://gcc.godbolt.org).

Nope, no warnings at all for spectral_contrast.c with GCC, ICC, or Clang even
with "-Wall -Wextra -pedantic". Then I thought to try it on MSVC at
[http://webcompiler.cloudapp.net/](http://webcompiler.cloudapp.net/). To my
surprise, it caught it pretty clearly with /W4:

    
    
      main.cpp(11): warning C4244: '/=': conversion from 'double' 
                    to 'float_t', possible loss of data
    

With that hint, I searched for other GCC warnings and found -Wconversion.
Indeed, with that (or -Wfloat-conversion) GCC picks up the scent pretty well:
[http://goo.gl/9xq3fG](http://goo.gl/9xq3fG)

    
    
       In function 'void normalize(float_t*, int)':
       11 : warning: conversion to 'float_t {aka float}' from 
            'double' may alter its value [-Wfloat-conversion]
    

ICC gives an excellent error message with -Wconversion also, perhaps the
clearest of the bunch: [http://goo.gl/cjXLjq](http://goo.gl/cjXLjq)

    
    
       warning #2259: non-pointer conversion from "double" to 
                      "float_t={float}" may lose significant bits
           for(i = 0; i < length; i++) v[i] /= magnitude;
    

Clang remained silent with all the options I tried, but perhaps I missed the
right one.

~~~
saghul
Did you try with -Weverything on Clang? That will enable more warnings than
-Wall and -Wextra.

~~~
nkurz
Thanks for mentioning that option. I hadn't known about it.

Clang does give a warning with -Weverything, but I don't understand what it
means: [http://goo.gl/M9qjmx](http://goo.gl/M9qjmx)

    
    
      13 : warning: no previous prototype for function spectral_contrast' [-Wmissing-prototypes]
           double spectral_contrast(float_t *a, float_t *b, int length) {
    

It gives the same warning if I change all the float_t's to float, or if I
change all the float_t's to double, so I think it's not actually useful or
relevant.

~~~
3JPLW
It's effectively catching the fact that `spectral_contrast.c` does not
`#include "match.h"` — this is indeed directly a part of the underhandedness.

The warning occurs because the function is not static — and therefore callable
by other modules. Since it's missing a forward definition (a previous
prototype), those modules must blindly declare the prototypes themselves… and
their prototypes can get out of sync with the actual definition. That's what's
happening here. `match.h` has the forward prototype, but it's very subtly
different from the definition. Were match.h included, there'd be a much more
glaring warning (or maybe even error).

------
72deluxe
This is really great!

Reading through the source made me look twice though, as I am used to writing
C++ so seeing variables defined but not initialised, non-const array starting
points as parameters with a separate length parameter (instead of just a
reference to a container or a const reference to enforce read-only nature),
memcpy instead of copy constructors or copy assignment operators.

Basically, it made me realise how impossible I would find it to write good C!

Really clever entry though, very impressive. I spotted all the issues I
mentioned above, looking for mistakes in them and completely missing the
actual problem.

~~~
pjmlp
> Basically, it made me realise how impossible I would find it to write good
> C!

That was my thought when the comparison was with Turbo Pascal 6.0.

Luckily in the same year I got Turbo C 2.0, someone made me aware that the
school also had the newly released Turbo C++ 1.0 available.

Since then, using C instead of C++ or better alternatives, only when I didn't
have an option to do so.

------
nkurz
Beautiful. I'd just looked up float_t, and realized that typedef'ing it to
double was almost certainly a 'tell', but I still failed to spot the failure
to include the header.

I presumed it was simply going to try to slip in a 'float' for a 'float_t' and
hope it wasn't noticed, although it seemed unlikely to be a winning strategy.

One other thing that seemed odd was the continued use 'double' after the
typedef. I wonder if there's a way to make it work where all the usages are
replaced by 'float_t'.

~~~
scatters
> I wonder if there's a way to make it work where all the usages are replaced
> by 'float_t'.

Yes, in fact you don't have to change anything else. The trick is that on
x86-64 float is promoted to double for argument passing, so the mismatch in
the return type on spectral_contrast has no effect.

------
ibotty
here is the blog entry of linux akesson, the winner about his entry.
[https://news.ycombinator.com/edit?id=11032712](https://news.ycombinator.com/edit?id=11032712)

~~~
khgvljhkb
Just FYI his name is Linus (just like Linus Torvalds). It's a common name for
Swedes (Torvalds in from the Swedish minority in Finland).

The Linux name is a play on Linus' name.

The Å in Åkesson can be typed on a US keyboard by hitting alt+a. To make ä & ö
you'd hit `alt+u a` and `alt+u o`. To make a ø, which is the Norwegian/Danish
way to say ö, you type `alt-o`.

EDIT: the keyboard things are on a US layout on a Mac. For a standard keyboard
it might be the same, or not. I don't know...

~~~
exprx
>Torvalds in from the Swedish minority in Finland

Torvalds is from the Swedish-speaking minority in Finland.

~~~
khgvljhkb
At least in Swedish they are called "Finlandssvenskar", which means Finland-
swedes. That is why I count them as Swedes just like the Swedes living in
Sweden, Norway, Denmark or anywhere else.

