Not so much "obfuscated C" as it is "embedding a binary into a C program". You can still do something similar with modern compilers:
char code[] = { /* put your bytes here */ };
((void(*)())code)();
I believe it is technically UB, but it does exactly what you'd think it does, and if compilers started doing funny things with it, you wouldn't be able to write things like JITs at all. A tiny demonstration of this can be found at the bottom of C4x86: https://github.com/EarlGray/c4/blob/master/c4x86.c
> Not so much "obfuscated C" as it is "embedding a binary into a C program".
The meaning of "obfuscated C" as the contest requires was not well-defined at that time and had to be amended for a very long time. There are at least 5 more entries that abused and subsequently changed the rules at that time [1] [2] [3] [4] [5]. ([6] is an exception; this kind of abuse of the rules is allowed and now common.)
> [...] if compilers started doing funny things with it, you wouldn't be able to write things like JITs at all.
The IOCCC can use a UX improvement where they have, for each entry, pages with an introduction, the hints page, how the thing works, the actual code and what happens when you run it (including output).
As it stands, it's very interesting to read but most examples are hard to run and I always end up going away unfulfilled.
This is why I do these write ups, I want to document the most obtuse pieces of code I can and explain the logic in a clear way =) I'll be writing more so be on the look out!
In other words, this type of behavior can be summarized as: Instead of waiting for other people to exploit your program in C, why not to execute some shellcode and pwn yourself while you're at it... /joke
The author says “I tried to define ‘main’ as an array of shorts with a modern compiler and it did not like that one bit”, but without saying which modern C compiler or what it didn’t like about it.
This sort of trick should still be possible with modern compilers. GCC has the charming warning
warning: ‘main’ is usually a function [-Wmain]
if main is declared as something other than a function.
Author of the article here. This was simply meant to be a minor observation, the focus of the article is not an investigation about the various ways to define main in your program.
Anyway, this is the error I got if you're curious. (I left such things out because the article was getting long as is)
warning: variable named 'main' with external linkage has undefined behavior [-Wmain]
short main[] = { 16, 18 };
I’m sorry your comment has been downvoted. I can’t imagine why. Thanks for writing an interesting article.
I realise this was a minor observation on your part, and I was remarking on it in that spirit. I’m sorry not to have made that clearer. I’ve found it rather dispiriting when writing of mine has been posted here, and the comments have seemed like nitpicking criticism, so I regret having given you that impression. One has to remind oneself that people who enjoy the article and have nothing to add will usually not leave comments, and so the comments give a misleading impression of how people felt about it.
The message you quote above appears to be a warning, rather than an error.
No harm no fowl, I appreciate constructive criticism but sometimes I'm on edge posting in these forums. It's like, this content is being posted to some of the best in the field - I want to be as precise and accurate as I can be.
It's fairly important reminder that pretty much every program we write has huge numbers of contextual and environmental assumptions built in - not just the obvious OS and envvars but things like the business model, the assumptions about how other parts of an organisation will react to certain outputs - it is often amazing to me that any piece of code can be understood by "outsiders" - we all are writing obfuscated code.
Having grown up coding assembly on the MC68000 (Europe, Amiga, demos ...) and spent years doing low-level embedded development on ARM Cortex cores it's really fascinating to see how similar they both are to the PDP.
IKR? I had an Atari ST which I coded in ASM and then I was in college and they had a PDP and the prof let me look at the ASM books and I was astounded!
It still compiles (without warnings) and runs on modern VAX systems (NetBSD 9, gcc 7.4.0, VAXstation VLC):
claire: {4} cc --version
cc (nb3 20190319) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
claire: {5} cc mullender.c -o mullender
claire: {6} ./mullender
:-)
claire: {7} uname -p
vax
Are you the VAX assembly expert I've been looking for? Can you explain some things (specifically the code after the PDP section)? If so e-mail me, I'd love to ask some questions. (The e-mail addr is easily found on my website)
Christopher Mills' winning entry for the 25th IOCCC (2018) is a PDP-11 emulator. Included with the BSD 2.9 image is the mullender.c entry -- you can compile and run it.
Beauty is in the eye of the beholder, and in my case, I find it very hard to look at any dark theme for more than a very brief amount of time. I'm wondering whether I've got some eye condition but I know from previous comments that there are at least a few other folks on HN who experience the same.
Thanks for your consideration. I used to have a "readability" bookmarklet in my browser that was gold for cases like this. But at some point these stopped playing nicely with the various script/tracking blocker add-ons I have installed, so there's that.
Indeed the code is not very difficult (except for that f'ing VAX), it's the manner in which they accomplished it + the personal stories that I think really make this cool (I wrote it though so I'm a bit biased).
In the future I'm going to dissect more complicated obfuscated programs so I hope you'll get to enjoy those.