Reputation: 33
I am new to C and I eagerly want to know by what magic this segment of code works?
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
The source can be found here:http://www.ioccc.org/1984/anonymous.c
And the following is a hint that comes with the code:
Dishonorable mention: Anonymous
The author was too embarrassed that he/she could write such trash, so I promised to protect their identity. I will say that the author of this program has a well known connection with the C programming language. This program is a unique variation on the age old "Hello, world" program. What reads like a read may be written like a write! Copyright (c) 1984, Landon Curt Noll. All Rights Reserved. Permission for personal, educational or non-profit use is granted provided this this copyright and notice are included in its entirety and remains unaltered. All other uses must receive prior permission in writing from both Landon Curt Noll and Larry Bassel.
Upvotes: 3
Views: 1767
Reputation: 206697
When you have an obfuscated code, you'll need to cleanup physical layout, add some white space, add the necessary indentation, and then compile the code. The warnings from the compiler will tell you a lot about some of the things the program hides.
First Cut Simplification - Add Whitespace
int i;
main()
{
for( ; i["]<i;++i){--i;}"];
read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
}
read(j,i,p)
{
write(j/p+p,i---j,i/i);
}
When the program is compiled using gcc -Wall
, I get the following warnings:
soc.c:2:1: warning: return type defaults to ‘int’ [enabled by default]
main()
^
soc.c: In function ‘main’:
soc.c:4:4: warning: implicit declaration of function ‘read’ [-Wimplicit-function-declaration]
for( ; i["]<i;++i){--i;}"]; read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
^
soc.c:4:50: warning: unknown escape sequence: '\o' [enabled by default]
for( ; i["]<i;++i){--i;}"]; read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
^
soc.c: At top level:
soc.c:7:1: warning: return type defaults to ‘int’ [enabled by default]
read(j,i,p)
^
soc.c: In function ‘read’:
soc.c:7:1: warning: type of ‘j’ defaults to ‘int’ [enabled by default]
soc.c:7:1: warning: type of ‘i’ defaults to ‘int’ [enabled by default]
soc.c:7:1: warning: type of ‘p’ defaults to ‘int’ [enabled by default]
soc.c:9:4: warning: implicit declaration of function ‘write’ [-Wimplicit-function-declaration]
write(j/p+p,i---j,i/i);
^
soc.c:9:17: warning: operation on ‘i’ may be undefined [-Wsequence-point]
write(j/p+p,i---j,i/i);
^
soc.c:9:17: warning: operation on ‘i’ may be undefined [-Wsequence-point]
soc.c:10:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
Second Cut Simplification - Un-obfuscation
Based on the above warnings, the program can be un-obfuscated to:
int i;
void read(int j, char* i, int p);
void write(int j, char* i, int p);
int main()
{
for( ; i["]<i;++i){--i;}"];
read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
return 0;
}
void read(int j, char* i, int p)
{
write(j/p+p, (i--) - j, 1);
}
The above version has no compiler warnings and produces the same output.
Third Cut Simplification - Un-obfuscate more
The expression i["]<i;++i){--i;}"]
is used to run the loop 14 times. Simple as that. It can be simplified to i < 14
.
'-'-'-'
is the same as '-' - '-'
which equals to 0
.
'/'/'/'
is the same as '/' / '/'
which equals to 1
.
i+++"hello, world!\n"
is same as i++ + "hello, world!\n"
which is same as s + i++
where s
can be char const* s = "hello, world!\n";
The for
loop can be simplified to:
char const* s = "hello, world!\n";
for( ; i < 14; read(0, s+i++, 1));
Since the value of j
in read
is always zero, the implementation of read
can be simplified to:
void read(int j, char* i, int p)
{
write(0, (i--), 1);
}
The expression (i--)
can be simplified to just i
since decrementing as a side effect does not change the workings of the function. In other words, the above function is:
void read(int j, char* i, int p)
{
write(0, i, 1);
}
When we realize that the value of argument j
is always 0
and the value of argument p
is always 1
, we can change the for
loop in the main function to:
for( ; i < 14; i++)
{
write(0, s+i, 1);
}
Hence, the entire program can be simplified to:
void write(int j, char const* i, int p);
int main()
{
int i = 0;
char const* s = "hello, world!\n";
for( ; i < 14; i++ )
{
write(0, s+i, 1);
}
return 0;
}
Fourth Cut Simplification - Make It Trivial
The above version has a hard coded number 14
. That is the number of characters in s
. Hence, the program can be made trivial by changing it to:
void write(int j, char const* i, int p);
int main()
{
write(0, "hello, world!\n", 14);
return 0;
}
Upvotes: 15
Reputation: 1842
Let's rewrite a bit the code, replace some expressions and add comments
int i; // i = 0 by default
main()
{
for( ;
"]<i;++i){--i;}" [i]; // magic: it is the same as i["]<i;++i){--i;}"];
// the important part is that there's 14 chars in the
// string, same length that "hello, world!\n"
// the content of the string has no importance here,
// in the end 'i' will go from 0 to 14
read(0, // since '-' - '-' is equal to 0,
"hello, world!\n" + (i++), // same as i+++"hello, world!\n"
// it is pointers arythmetic
// the second arg to the read
// function defined further points
// to the letter to print
1)) // '/' / '/' division result is 1
;
}
// the read function is then always called with
// j == 0
// i is a pointer to the char to print
// p == 1
// And for the obfuscation fun, the read function will write something :)
read(j,i,p)
{
write(0, // j/p+p is equal to 0, which is the stdout
i, // i-- - j is equal to i, decrement of i comes later
1); // i / i is equal to 1, this means one char to print
}
Upvotes: 4