2006 Competition
In conjunction with the 12th International Erlang User Conference, an Erlang Obfuscated Programming Competition was held. The goal of this competition was to write the most obfuscated Erlang program, providing a safe forum for poor coding practices and programming styles. Through this competition, we hope to illustrate some of the subtleties of Erlang and how they can best be used and abused.
A report from the judges
This year's "Subject Matter Experts" were
Mats Cronqvist, Ericsson, Hungary
Jan Nystrom, Erlang Solutions, UK
Kostis Sagonas, Uppsala University, Sweden
Erik Stenman, Kreditor, Sweden
A call for participation to the competition was made at the Erlang workshop in Portland. That we got fewer submissions than last year reflects well the feeling we have that the Erlang area is really hotting up. All provided submissions were ingenious, making it so hard to pick a winner that it became a draw. The judges individually gave every entry a grade between 1 - 5 in the following categories:
- Obfuscation
- Style
- Innovation
- Functionality
When adding up the grades, we had not one but two distinct winners.
Winners (in no particular order)
- 1st Prize, Richard Carlsson
- 1st Prize, Laurent Picouleau
First Prize : Richard Carlsson
First prize goes
to Richard Carlsson for a program that "shows the level of obfuscation
that easily can be achievedby the powerful but all to seldom used
process flag - 'error_handler'." It is a strikingly simple program,
which is wholly incomprehensible if one does not understand how the
Erlang system deals with undefined functions.
Here is the code:
-module(obf).
-compile(export_all).
undefined_function(_, _, []) -> [];
undefined_function(M, r, As) ->
apply(M, r, tl(As)) ++ [hd(As)];
undefined_function(M, c, As) ->
apply(M, r, hd(As)) ++ apply(M, c, tl(As)).
run() ->
process_flag(error_handler, obf),
obf:c(",olleH", " gnalrE ", "sresU", "!").
This is what happens when you run the program:
Eshell V5.5.1 (abort with ^G)
1> c(obf).
{ok,obf}
2> obf:run().
"Hello, Erlang Users!"
3>
Second Prize : Laurent Picouleau
Fisrt prize goes to Laurent Picouleau for
a program that in sharp contrast to the other winner is no way simple.
The program is a Sudoku solver which through the extensive use macros
creates a practically unreadable program. But what caught the eye of
all judges, is the creative naming of modules which confuses the
compiler and code loading system to the point where one has to manually
rename one of the generated BEAM files to be able to run the program.
Here follows a sample of the code:
-module('').
-export(['"'/1,''/4,'|'/3,'_'/3]).
-include(".hrl").
p(N)?w ?i_i(N),N>1->?l_e(1,N*N).
'"'(S)?w ?i_i(S),1<S->
#b{s=S,c=[{{L,C},?MT,p(T)}||
T<-[S],L<-?l_e(0,S*S-1),C<-?l_e(0,S*S-1)]}.
''(B,_,_,'_')->{ok,B};
''(B,L,C,V)->
?k ?l_s({L,C},1,B#b.c)of
{?v,{{L,C},?MT,P}}->
?k ?l_m(V,P) of
?f ->{v_f,B};
?t ->
S=B#b.s,D=?l_r({L,C},1,B#b.c,{{L,C},V,[]}),
E=u(L,C,V,D,S),
{ok,#b{s=S,c=E}}
?z;
{?v,{_,V,_}}->{ok,B};
{?v,{_,_,_}}->{a_s,B}
?z.
u(L,C,V,E,S)->{H,I,D}='|'(L,C,S),u(H++I++D,V,E).
u([],_,L)->L;
u([C|T],V,L)->
{?v,{_,S,P}}=?l_s(C,1,L),
N=P--[V],
R=?l_r(C,1,L,{C,S,N}),
u(T,V,R).
'|'(L,C,S)->A=S*S-1,B=L-L ?r S,D=C-C ?r S,
{[{X,Y}||Y<-?l_e(0,A),(Y<D)or(Y>=(D+S)),X<-[L]],
[{X,Y}||X<-?l_e(0,A),(X<B)or(X>=(B+S)),Y<-[C]],
[{X,Y}||X<-?l_e(B,B+S-1),Y<-?l_e(D,D+S-1),{X,Y}=/={L,C}]}.
'_'(A,B,C)->D=A-A ?r C,E=B-B ?r C,F=C*C-1,
{[{X,Y}||Y<-?l_e(0,F),X<-[A]],
[{X,Y}||X<-?l_e(0,F),Y<-[B]],
[{X,Y}||X<-?l_e(D,D+C-1),Y<-?l_e(E,E+C-1)]}.
This is what happens when you run the program:
Eshell V5.5.1 (abort with ^G)
1> make:all([load]).
Recompile: "
Recompile: ''
** Module name '''' does not match file name '"''"' **
Recompile: oss
Recompile: oss_test
up_to_date
2> oss_test:test_easy().
=ERROR REPORT==== 11-Dec-2006::22:26:25 ===
Error in process <0.31.0%gt; with exit value:
{undef,[{'','"',[3]},
{oss_test,create,2},
{oss_test,test_easy,0},
{erl_eval,do_apply,5},
{shell,exprs,6},
{shell,eval_loop,3}]}
** exited: {undef,[{'','"',[3]},
{oss_test,create,2},
{oss_test,test_easy,0},
{erl_eval,do_apply,5},
{shell,exprs,6},
{shell,eval_loop,3}]} **
3> os:cmd("mv "''.beam" ".beam"").
[]
4> oss_test:test_easy().
oss_test:test_easy().
[[-1,1,-1,2,9,7,-1,-1,8],
[-1,2,-1,3,5,-1,1,9,-1],
[5,-1,3,-1,-1,-1,7,-1,6],
[-1,-1,6,1,-1,5,2,7,3],
[2,7,5,6,-1,3,8,1,9],
[8,3,1,7,-1,9,6,-1,-1],
[3,-1,9,-1,-1,-1,5,-1,2],
[-1,5,2,-1,6,8,-1,3,-1],
[4,-1,-1,5,3,2,-1,6,-1]]
[[6,1,4,2,9,7,3,5,8],
[7,2,8,3,5,6,1,9,4],
[5,9,3,8,1,4,7,2,6],
[9,4,6,1,8,5,2,7,3],
[2,7,5,6,4,3,8,1,9],
[8,3,1,7,2,9,6,4,5],
[3,6,9,4,7,1,5,8,2],
[1,5,2,9,6,8,4,3,7],
[4,8,7,5,3,2,9,6,1]]
ok
5>









