3

I copied this below code from Stack Overflow's 404 Not Found Error Page.

# define v putchar
# define print(x)
main(){v(4+v(v(52)-4));return 0;}/*
#>+++++++4+[>++++++<-]>
++++.----.++++.*/
print(202*2);exit();
#define/*>.@*/exit()

The above code compiles fine and prints 404 on the console. I thought the statement print(202*2); is responsible for printing 404, but I am not right because changing the numbers in this statement also prints 404.

Could somebody help me to understand this code and how it prints 404?

Am posting the compilation output for your reference as there are comments saying this code doesn't compile. The file containing above code is Test.c.

gcc Test.c -o Test

Test.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int] main(){v(4+v(v(52)-4));return 0;}/* ^ Test.c: In function ‘main’: Test.c:1:12: warning: implicit declaration of function ‘putchar’ [-Wimplicit-function-declaration] # define v putchar ^ Test.c:3:8: note: in expansion of macro ‘v’ main(){v(4+v(v(52)-4));return 0;}/* ^ Test.c: At top level: Test.c:6:14: warning: data definition has no type or storage class print(202*2);exit(); ^ Test.c:6:14: warning: type defaults to ‘int’ in declaration of ‘exit’ [-Wimplicit-int] Test.c:6:14: warning: conflicting types for built-in function ‘exit’

./Test

404

JSN
  • 2,035
  • 13
  • 27
  • 4
    putchar(52) outputs 4; 52-4 = 48; putchar(48) outputs 0; 48+4 = 52; putchar(52) outpus 4 again. – Jonathan Leffler Jun 28 '17 at 05:56
  • 8
    https://meta.stackoverflow.com/questions/252184/whats-the-joke-in-the-stack-overflow-404-page-code – msc Jun 28 '17 at 05:56
  • Just asking: Dear Migration to MSO voters: can you please add a little justification? I think I'm missing something here on why is should be migrated? – Sourav Ghosh Jun 28 '17 at 06:14
  • @SouravGhosh; It should be migrated because it has been asked on meta stackoverflow and there are some good answer already there. – haccks Jun 28 '17 at 06:24
  • It doesn't. The code won't compile for multiple reasons. I doubt the code is even C. – Lundin Jun 28 '17 at 06:25
  • @haccks Thanks, but just one thought, does that migration not allow for more questions on SO for this in future? – Sourav Ghosh Jun 28 '17 at 06:25
  • @Lundin - I was able to compile the code with few warnings using gcc and execute it successfully. – JSN Jun 28 '17 at 06:26
  • 1
    @Beginner No, it is impossible to compile this on a standard-compliant C compiler without rewriting most of it. – Lundin Jun 28 '17 at 06:28
  • @SouravGhosh; Does SO meant for such questions? And if you think you can answer better than the answers provided on meta then you are welcome. – haccks Jun 28 '17 at 06:36
  • @Beginner Compile it as C language instead of GNU language: `gcc -std=c11 -pedantic-errors`. – Lundin Jun 28 '17 at 08:12
  • I made a much more intricate example which does compile cleanly on a standard compliant compiler. Added to my answer below :) – Lundin Jun 28 '17 at 08:14

4 Answers4

2

Cannot use a meta-question as dupe, so blatantly copying from the MSO answer.

Since this is tagged and mentioned "compiled", so just extracting the C part of it.

Credits: Mark Rushakoff is the original author of the polyglot.

The C code is fairly easy to read, but even easier if you run it through a preprocessor:

main(){putchar(4+putchar(putchar(52)-4));return 0;};exit();

Your standard main function is declared there, and exit is also declared as a function with an implicit return type of int (exit is effectively ignored).

putchar was used because you don't need any #include to use it; you give it an integer argument and it puts the corresponding ASCII character to stdout and returns the same value you gave it. So, we put 52 (which is 4); then we subtract 4 and output 0; then we add 4 to output 4 again.

Also, a little more elboration, from [Cole Johnson's] (https://meta.stackoverflow.com/users/1350209/cole-johnson) answer

Disregarding all of that, when we reformat the code a bit, and replace 52 with its ASCII equivalent ('4'), we get:

int main() {
    putchar(4 + putchar(putchar('4') - 4));
    return 0;
}

As for the putchar declaration, it is defined by the standard to return it's input, like realloc. First, this program prints a 4, then takes the ASCII value (52), subtracts 4 (48), prints that (ASCII 0), adds 4 (52), prints that (4), then finally terminates. This results in the following output:

404

As for this polyglot being valid C++, unfortunately, it is not as C++ requires an explicit return type for functions. This program takes advantage of the fact that C requires functions without an explicit return type to be int.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 2
    Should vote for transfer onto meta then. Where it can be closed as a dup. – StoryTeller - Unslander Monica Jun 28 '17 at 06:11
  • 1
    @StoryTeller But it __is__ a valid question in SO. it's about the code understanding, not about the working of SO....right? I understand the context is overlapping, but it's not OT here, either...What do you think? – Sourav Ghosh Jun 28 '17 at 06:12
  • I agree this is a valid topic in SO ^^. Maybe make a wiki answer. In fact this is the meta question that is off topic. – Stargateur Jun 28 '17 at 06:13
  • 2
    I think that we should not be answering questions over and over again. This overlaps with meta, and meta has a perfect answer for it. – StoryTeller - Unslander Monica Jun 28 '17 at 06:16
  • 1
    If the code were ever likely to be encountered in "The Real World™" then it should stay here. Given the code's SO specificity, Meta is probably the place for it. – TripeHound Jun 28 '17 at 07:06
1
# define v putchar

this defines v as the putchar() function. It prints a character and returns it.

# define print(x)

this defines print(x) as nothing (so print(202*2) means nothing)

main(){v(4+v(v(52)-4));return 0;}/*

this could be rewritten as:

main()
{
  putchar(4 + putchar(putchar(52) - 4));
  return 0;
}

it is using ASCII codes to print '4' (code 52), '0' (code 52 - 4 = 38) and again '4', so "404".

That line ends with a /* starting a comment the continues through the next two lines:

#>+++++++4+[>++++++<-]>
++++.----.++++.*/

The line below turns out empty, but it is a bit tricky because exit() is defined as empty AFTER the line itself. That works because the C preprocessor runs BEFORE the compilation.

print(202*2);exit();

The line below defines exit() as empty, used on the line above.

#define/*>.@*/exit()
flaviodesousa
  • 7,255
  • 4
  • 28
  • 34
1

The code cannot compile on a standard C compiler, such as gcc -std=c11 -pedantic-errors.

1) main must return int on hosted systems.
2) putchar() must have #include <stdio.h>.
3) You can't write semicolons outside functions.

After fixing these beginner-level bugs and removing all superfluous fluff that doesn't do anything but creating compiler errors, we are left with this:

#include <stdio.h>
#define v putchar
int main(){v(4+v(v(52)-4));return 0;}

This revolves around putchar returning the character written:

putchar(4+putchar(putchar(52)-4));
  • 52 is ASCII for '4'. Print 4.
  • 52 - 4 = 48, ASCII for 0. Print 0.
  • 4 + 48 = 52. Again print 4.

And that's it. Very bleak as far as obfuscation attempts go.


Proper, standard-compliant obfuscation would rather look something like this:

#include <stdio.h>
#include <iso646.h>

??=define not_found_404(a,b,c,d,e,f,g,h,i,j)a%:%:b%:%:c%:%:d%:%:e%:%:f(\
(g%:%:h%:%:i%:%:j<::>)<%'$'+d##o%:%:e not "good",g??=??=ompl ??-- -0163l,\
((void)(0xBAD bito##b not "bad"),not "ugly")??>,(g%:%:h%:%:i%:%:j??(??)){\
((c%:%:d%:%:e)- -not "lost")     <:??=a??) -??-??- '<',\
((c%:%:d%:%:e)- -not "found")    <:??=b??) -??-??- 'B',\
((c%:%:d%:%:e)- -not 0xDEADC0DE) <:??=c??) -??-??- '5',\
((c%:%:d%:%:e)- -6##6##6 xo##b- -6##6##6)%>)

int main()
{
  not_found_404(p,r,i,n,t,f,c,h,a,r);  
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • "You can't write semicolons outside functions.", What ? you mean instructions ? By the way, proto of `main()` should be `int main(void);` in this case so you are not compliant :p. – Stargateur Jun 28 '17 at 08:27
  • @Stargateur `print(202*2);exit();` gets interpreted as `;exit();` which is nonsense. GCC gives the error "ISO C does not allow extra ';' outside of a function". And no, the form of main() may take any parameters and the standard isn't really clear. https://stackoverflow.com/a/31263079/584518 – Lundin Jun 28 '17 at 08:38
  • This is not an obfuscation attempt. It's a polyglot code. – bolov May 09 '18 at 21:00
  • @bolov No it isn't, as demonstrated above. A polyglot is code that compiles in multiple languages. – Lundin May 10 '18 at 20:04
  • @Lundin https://meta.stackexchange.com/a/27846/254429 it runs and has the same output in Befunge-93, Brainf*ck, Python, Ruby, Perl, and C. Okey I get your point not standard C, but still... – bolov May 10 '18 at 20:18
0

you have defined V as putchar() which take ascii code of char to be printed and return ascii value of printed char. execution of your program will start from the main as bellow first v(52) will print 4 and return 52 second v(52-4) will print 0 (48 is ascii value of 0) and return 48 finally it will call to v(48+4) will print 4 as 52 is ascii value of '4'.

Jatin Parmar
  • 2,759
  • 5
  • 20
  • 31