How does this code print 404?
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
# 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()
Cannot use a meta-question as dupe, so blatantly copying from the MSO answer.
Since this is tagged c 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
.
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));
'4'
. Print 4. 0
. Print 0. 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);
}
链接地址: http://www.djcxy.com/p/73606.html
上一篇: 未定义的参考`pthread
下一篇: 这段代码如何打印404?