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 Nyström, Erlang Training and Consulting, 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. The rules of the competition are available
here. 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)
First Prize: Richard Carlsson First prize goes to Richard Carlsson for a program
that "shows the level of obfuscation that easily can be achieved
by 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:
%% File: .erl
%% created: 14 Sep 2005
%% Author: Laurent Picouleau <laurent_at_nerim.net>
-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>
|