http://www.perlmonks.org?node_id=424355

Perl is famous for its ability to create programs that are entirely illegible to everyone but the developer who wrote them. The Perl community even has obfuscation contests to see who can write the most unintelligible Perl code.

-- Andrew Clinick, Microsoft Scripting Program Manager in Perl of Wisdom

it's almost depressing to think that someone might actually believe this. Programmers, not languages, write obfuscated code; and Perl certainly didn't invent the concept.

-- brian d foy response on comp.lang.perl.misc 16 February 1999

I may have become partially famous for my obscure one-liners here on Usenet, but when I write production code for hire, it's compact but readable and well-documented ... let us please stop passing around the myth that Perl *is* write-only code, or *encourages* write-only code.

-- Randal L. Schwartz response on comp.lang.perl.misc 1st March 1999

Let me begin this meditation on recreational obfuscation by reaffirming brian_d_foy's and merlyn's responses above: Perl is indeed a fine language for writing compact yet readable and maintainable systems.

Though Obfuscation has no place in production code, writing deliberately obfuscated code as a recreational pastime forms a proud part of Perl's history and culture -- a fun way to explore TMTOWTDI and the rich expressiveness of the language.

Obfu participation, of course, is optional, and many Perl programmers have no interest in it. Indeed, the following Perl generalissimos have never fired an obfuscated monastic projectile in anger: vroom, merlyn, dws, dragonchild, davorg, Elian, brian_d_foy, TheDamian and TimToady (though, admittedly, Tim did flirt briefly with C obfus in the mid 1980s). In case you're interested, from the PM top 40, the most prolific obfuscator is number 23, davido, with 30 obfuscated notches in his belt.

This, the third part of the seemingly never-ending series on the lighter side of Perl culture, focuses on artistic (or recreational) obfuscation. Naturally, I won't waste time on obfuscation for job security or, horrors, for perverse and futile attempts to close open source.

History

Obfuscated code began long before Perl did. In 1972, for example, Messrs Woods and Lyon outraged the conservative IBM/Cobol world by implementing INTERCAL on an IBM 360. Not to mention the International Obfuscated C Code Contest of '84, contested over three years before Perl's glitzy launch on 18 December 1987.

Perhaps the earliest example of obfuscated Perl code were some JAPHs concocted by merlyn in the early 1990s. These early JAPHs, however, were only mildly obfuscated compared to those inspired by fierce competition in the TPJ-sponsored Obfuscated Perl Competitions, started in 1996, and run by Jon Orwant and Felix Gallo.

Another significant promoter of obfu is the Perl Monks web site, sporting a distinct Obfuscated Code section, containing around 500 compositions. Indeed, from over half a million nodes, the most popular PM node of all time is an obfuscated one, the famous camel code.

Finally, it should come as no surprise that the country hosting The Louvre is also home to many eminent Perl obfu artisans. In particular, the Paris Perl Mongueurs (sic) have a long tradition of artistic obfuscation, evident from one of the finest obfu pages on the web, $A++.

Constraints

The more constraints one imposes, the more one frees oneself of the chains that shackle the spirit... the arbitrariness of the constraint only serves to obtain precision of execution.

-- Igor Stravinsky, 1882-1971

Constraints are the heart of obfu. When viewed as an art form, obfu seems closest to poetry (which is constrained by rhyme and meter) and Oulipo (formal constraints in literature, a famous example being Georges Perec's 300 page novel "La Disparition", written without using the letter 'e').

Perl obfu constraints might be classified as follows:

  • Hard for human reader to understand
  • JAPH
  • $A++
  • Restricted character set
  • Restricted Perl subset
  • Ascii art
  • Size
  • Perform a specified function
  • Multi-lingual
  • Quine
  • Palindromic

Further to the above list, obfu specialists are always on the lookout for an original and surprising new constraint.

Hard for Human Reader to Understand

An obfu should be made as difficult as possible to comprehend, not only by using cheap tricks -- such as y}}}c instead of length -- but by employing unnatural algorithms. For some general tips on how to make code harder to understand, see Learning from Obfuscation. A fine example of an unnatural algorithm is described by MJD here.

JAPH

An obfuscated JAPH is constrained to output the string "Just another Perl hacker," -- for more information on JAPHs, see The Lighter Side of Perl Culture (Part II): JAPH.

$A++

$A++ is a deformation of "A plus" which is itself the common way to shorten "A plus tard". It is for the French what "see you" is to "see you later" in English.

-- stefp

And for the Australians, what "see ya" is to "see ya later mate" (or "see ya later cobber").

-- eyepopslikeamosquito

💲🅰🙋

Like the JAPH, the $A++ is just an arbitrary canonical program. An $A++ does not emit anything, it simply increments the variable $A. Traditionally, it's a parting word to end an email with, so it should be short.

The first $A++ was composed by BooK on Friday Oct 15 1999:

$A = eval q.@{[.."0,"x$A.qq|0]}|
Not bad for a first attempt! A bit more interesting than the first JAPH. ;-)

From the BooK archives, here are the earliest $A++s:

1999/10/15 BooK $A = eval q.@{[.."0,"x$A.qq|0]}| 1999/11/04 BooK $A =~ s/$A/$A+1/e 1999/11/04 Moun inc( $a, $a, $tchoum ); sub inc { map { s/^(.*)$/$1 ++1/e; } @_ } 2000/01/31 BooK for(map{2**$_}(0..31)){if(($A&$_)==0){$A|=$_;last}else{$A&=~$_}} 2000/02/18 BooK $A+=@{[$A]} 2000/02/21 Moun $A = ((@S=("($A==$S[1])?($S[1]+1):(($S[1]++,eval($S[0]))[1])",0)),eval($S[0 +]))[1] 2000/03/13 BooK $A =~ s/(-)?(\d+(?:\.\d*)?)/$1.($2+($1?-1:1))/e 2000/03/13 BooK $A =~ s/(-)?(\d+(?:\.\d*)?)/"$1 1+"x$2.'1'/egoisme 2000/03/17 BooK $A+=0<<1|2<<3>>4 2000/03/24 BooK $A=~s/(-)?(\d+(?:\.\d*)?)/# les filles c'est des cl +oches (Souchon) "$1 1+"x$2.'1'/sexisme 2000/03/30 BooK $A=@{[($A)x$A,$A]} 2000/03/30 BooK $A=~s/($A)/$1+1/e 2000/03/31 BooK A:goto(A)if$A!=$A+++1 2000/04/05 BooK $A=$A{$A}?&{$A{$A}}($A):&{$A{$A}=sub{1+shift}}($A) 2000/04/05 grinder $a = do{ while(1&$a) {$a>>=1}continue {++$b}($a|1)< +<$b }; 2000/04/06 grinder $a = do{$_=!$_;$_<<=1 while($a&$_<<1<=$a);($a&$_|1)+($a&$_&&$a&~$_|1||$a& +~$_)}; 2000/04/11 stefp ${ '`' | '!' } -= $#$ + ${""} - ${''} 2000/04/11 stefp $ {'`'| '!'}-=-- +$#$+ $ { ""}- --$ { ''} 2000/04/12 BooK *A=\($A+1) 2000/04/12 grinder use Cobol; PROCEDURE DIVISION ADD 1 TO A GIVING B MOVE B TO A 2000/04/12 grinder $A = do{$_=!$_;$_<<=1 while(${'@'|'!'&~'"'}>=${'@'|'!'&~'"'}&$_<<1);(${'@'|'!'&~'"'}&$_|1)+( +${'@' |'!'&~'"' }&$_&&${'@'|'!'&~'"'}&~$_|1||${'@'|'!'&~'"'}&~$_)}; 2000/04/13 stefp use AI; incrémente la variable scalaire a de 1 unité +# $a++ 2000/04/13 stefp ${"A\0comme quoi perl n'ignore pas partout les \0"} +++

On Apr 12 2000, grinder proposed that these $A++s be collected and put on an $A++ web page.

Update (2012): Re: your obfuscation magic! lists a couple of nice $A++ obfus

Restricted Character Set

In this $A++:

${~$/&~$;&$^}++
Nicholas Clark restrains himself to non-alphanumeric characters only. The converse, a speciality of mtve, is illustrated by another $A++:
y ccccd x s vvchr oct oct ord uc ave x s vvucve le s vvuc ave x s vvchr oct oct oct ord uc bve x eval

For obfus restricting themselves to not using any punctuation at all, see:

Restricted Perl Subset

Damian Conway's Extreme Perl -- The Horror That Is SelfGOL is an, er, horrific example, constraining itself to not importing any modules, and not using a single if, unless, while, until, for, foreach, goto, next, last, redo, map, or grep.

Constraints sometimes happen accidentally. When writing a little Sierpinski triangle generator, for example, I noticed it seemed to be using an awful lot of s/// operations ... so I naturally tried to make it use only this operator. Then, I noticed a lot of 'g' and 'e' characters ... so I tried to use as many of these as possible. None of this was planned, it just sort of happened. Here is the final result (it takes a command line argument (1-9) indicating the triangle size).

#!/usr/bin/perl -l s--@{[(gE^Ge)=~/[^g^e]/g]}[g^e]x((!!+~~g^e^g^e)<<pop).!gE-ge, s-[^ge^ge]-s,,,,s,@{[(g^';').(e^'?')]},(G^'/').(E^'|')^Ge,ge, print,s,(?<=/[^g^e])[^g^e][^g^e],$&^(G^'/').(E^'|')^gE,ge-ge

Ascii Art

The constraint here is that your code must fit into a specified shape. Some obfus are further constrained in that only certain characters may fill certain parts of the shape.

If you employ this style of obfu, strive to extend the theme defined by the shape to the source code itself. Note in camel code for example, Erudil's choice of variable names: $camel, @dromedary, @camelhump, and so on. To further illustrate, when tuning Saturn, I changed O^N^E}(@X,1.6) to S|A|T|U}(@R,$N) to better align the code to the Saturnian theme.

Size

There are often practical limits on the size of an obfu. In the TPJ Obfuscated Perl Contests, for example, the original 1024 character size limit was reduced by the judges to 512 bytes for OPC 5 -- which was a nasty spoiler for those entrants, such as BooK (Perl/Postscript obfu) and TheDamian (SelfGOL), who had prepared 1024-byte entries months in advance! Other obfu types limited by size are JAPH, $A++ and Ascii Art.

Overcoming size limits can be a chronic nuisance, requiring considerable golfing skills in addition to obfuscation ones. And significant golfing often spoils the artistic merit of the obfu.

Perform a Specified Function

A common constraint is to perform a specified function, such as fly through a Mandelbrot, as in Mandelbrot flythrough, or play a game, as in Space Invaders. Apart from playing games, spectacular visual effects and mathematical algorithms are popular choices for obfus.

Multi-Lingual (Polyglot)

Some early PM examples of these are P(ython|erl) (suck|rule)s! and BooK's C is Perl response to Ovid's Perl is C provocation.

BooK's prize-winning OPC 5 Perl/Postscript obfu can be found here.

Lyon's fiercely competitive Jerome Quelin tried to "out-BooK" BooK in his YAPC::Europe 2003 talk by showcasing an octo-lingual (perl, c, c++, befunge, brainf**k, python, ook, html/javascript) program that computed the Fibonacci series.

Update: For a list of polyglot references started by ambrus see: List of polyglot obfus (Re: Christmas poem since 1988).

Palindromic

An $A++ penned by the mtve:

!$A+++!q!+++A$!

Humour

When composing an obfu, always be on the lookout for opportunities to add humour -- as Abigail did in the classic Things are not what they seem like..

Exploring the Medieval Castle

Programming in Perl5 is like exploring a large medieval castle, surrounded by a dark, mysterious forest, with something new and unexpected around each corner. There are dragons to be conquered, maidens to be rescued, and holy grails to be quested for. Lots of fun.

-- Abigail in December 2002 Perl 6 Summary

Exploratory obfuscation is perhaps more fun in Perl than most languages. Why? For starters, there ain't no Ansi Perl. And there are numerous experimental, obsolete (e.g. D'oh not D::oh), half-baked (e.g. typed declarations) and undocumented (e.g. Japhy explains where behaviour of --$| is documented) features begging to be exploited by the evil obfuscator. Moreover, Perl offers more freedom and fewer limitations than most languages -- consider, for example, composing a Python Ascii Art obfu, given its ludicrous indentation rules.

Two sample exploratory $A++ obfus from stefp are:

%average::; print probably not my average $A++
and
sub _ : lvalue { $A }; ++_();

Perl 6 is expected to be less fun for the obfuscator. Most people consider this to be a feature, but not Abigail, who further opined: "Perl6 looks like a Louis-XVI castle and garden to me. Straight, symmetric, and bright. There are wigs to be powdered, minuets to be danced, all quite boring.".

Some Classic Obfus

There are many obfus I've never seen. Please let us know of any classic obfus I've overlooked.

Some Keen Perl Monk Obfuscators

Please let me know of any I have overlooked.

References

References Added Later

Bad code references:

Obfuscation Generators

Though I find these of academic interest, they are of little interest to obfuscators because they detract from artistic merit and originality. Two examples of these are Yet Another Obfuscation Engine and Acme::EyeDrops.

Is Obfu related to Golf?

As pointed out by champion golfer Eugene van der Pijll, there is usually little overlap between obfu and golf (the subject of the next installment of this series), a different mindset being required by each.

Occasionally however, a golfer accidentally produces a highly obfuscated solution in the heat of battle. In TPR(0,5a) (won by Eugene), for example, Michael Thelen commented: "How absolutely confusing! Replacing parens with whitespace makes this probably the most obfuscated program I've ever written" on his way to producing this infix to RPN converter:

#!perl -lp y/()^I /^I_/d+s@^I|(?<=\w)\D@($/=" $&$/")=~s#_(\C*?)^I|(\S)([ */${":"x/\G[+-]/}]*)#$2 #;$+@eg;$_.=$/;y/ / /s+chop

Acknowledgements

I would like to thank BooK and stefp for their help in preparing this article.

Other Articles in This Series

Updated June 2014: Added Magic 8 Ball to list of "Some Classic Obfus". Thanks ambrus for mentioning this. Nov 2018: Added list of polyglot references started by ambrus: List of polyglot obfus (Re: Christmas poem since 1988). Dec 2020: Added more comprehensive list of obfus restricting themselves to not using any punctuation characters at all (thanks BooK). Nov 2023: Added $A++ emoji from Perl Secret Operator Emojis