Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

The Lighter Side of Perl Culture (Part III): Obfu

by eyepopslikeamosquito (Canon)
on Jan 23, 2005 at 06:15 UTC ( #424355=perlmeditation: print w/ replies, xml ) Need Help??

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 generated by the fierce competition of the TPJ-sponsored Obfuscated Perl Competitions, started in 1996, and run by Jon Orwant.

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.

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
See also: Fun With Reserved Keywords, ppencode, exactly 390 bytes, Ode for getprotobyname, Indigo japh.

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

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.

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

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.

Comment on The Lighter Side of Perl Culture (Part III): Obfu
Select or Download Code
Re: The Lighter Side of Perl Culture (Part III)
by Anonymous Monk on Jan 24, 2005 at 03:13 UTC
    eyepopslikeamosquito writes:
    consider, for example, composing a Python Ascii Art obfu, given its ludicrous indentation rules.

    Considered, and accepted, sir: ObfuscatedPython

    yrs art-is-subjective-ly, -T.

    (but thanks for the articles - most interesting ;-)

        Golfing in Python is rare because good python code tends to be not very much longer than the shortest possible version. There's also less in the core than Perl and far fewer side effects/context-dependencies.

        That said, you occasionally see golfing - for example Wypy was golfed down from about 21 lines - and Java converts posting Java-ish Python to comp.lang.python tend to receive suggestions for how to reduce their code by about 70%... ;-)

        yrs Disciple-of-another-Faith-ly, -T.

Re: The Lighter Side of Perl Culture (Part III)
by Jenda (Abbot) on Jan 24, 2005 at 13:35 UTC

    I think we've been a bit unfair to Mr. Clinick. If you read the whole paragraph plus the previous one it's clear he did not mean that all Perl programs are write-only.

    Perl actually stands for Practical Extraction and Report Language and was invented by Larry Wall to help him develop solutions on UNIX that C and Shell scripts just didn't address. You could say that he invented "scripting" as we know it today. I'm convinced that I'll get a ton of mail about that (from avid Rexx and TCL programmers, no doubt), but I think Larry deserves a lot of the credit for developing scripting into the vibrant community it is today. It's difficult to describe Perl; it's similar in syntax to C—but is much easier to learn and develop, because it was designed to give you as many shortcuts as possible. Ask Perl developers to do something, and they invariably reply, "No problem. I could do that in two lines of Perl," closely followed by a colleague claiming it could be done in one line! That's not to say that you can't develop large programs in Perl. It's just that a lot of Perl scripts are very small because the language gives you those shortcuts.
    Sometimes, those shortcuts can be a little counterproductive, though. 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!

    I think the quote was taken out of context and thus may seem to mean something else than was intended.

    Jenda
    We'd like to help you learn to help yourself
    Look around you, all you see are sympathetic eyes
    Stroll around the grounds until you feel at home
       -- P. Simon in Mrs. Robinson

      I think we've been a bit unfair to Mr. Clinick.
      Agreed. The article as a whole is very positive towards Perl and hugely respectful of Larry Wall and his contribution to the scripting world.

      I included this quote because it contains a lesson: it shows how Obfuscation Contests can be used as a propaganda weapon to damage Perl's reputation. Since attempting to outlaw Perl obfu contests is clearly absurd, the best we can do to protect Perl's reputation is to respond promptly and accurately -- as brian_d_foy and merlyn did above. BTW, I heard a rumour (but I'm damned if I can find anything with google now) that O'Reilly did not sponsor the TPJ Obfuscated Perl Contests because they felt they would project the wrong image of Perl. Does anyone know if there is any truth to this rumour?

      Perl actually stands for Practical Extraction and Report Language
      To nitpick with Mr Clinick, I refer to the draft Oxford English Dictionary entry cited on history.perl.org:
      Perl Brit. Perl, perl, irreg. PERL Computing. perl n. , arbitrarily chosen for its positive connotations, with omission of -a- to differentiate it from an existing programming language called Pearl. Coined by Larry Wall in the summer of 1987; the program was publicly released on 18 December of that year. Acronymic expansions of the name (such as Practical Extraction and Report Language and Pathologically Eclectic Rubbish Lister), though found in the earliest documention for the language, were formed after the name had been chosen. Coinage details confirmed by personal communication from L. Wall, May 2000. A high-level interpreted programming language widely used for a variety of tasks and especially for applications running on the World Wide Web. The form Perl is preferred for the language itself; perl is used for the interpreter for the Perl language.
      I love it that PERL is considered "irregular". :-)

Re: The Lighter Side of Perl Culture (Part III)
by kutsu (Priest) on Jan 24, 2005 at 15:27 UTC
    There are many obfus I've never seen. Please let us know of any classic obfus I've overlooked.

    You meantion the camel but forget the llama ;). Actually if you want to see the best Obfu.s looking through Erudil's nodes is the best place to start, at time of this posting they had a combined rep of 2007 - that's an average of 286.7 rep per :).

    "Cogito cogito ergo cogito sum - I think that I think, therefore I think that I am." Ambrose Bierce

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://424355]
Approved by rlb3
Front-paged by itub
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (10)
As of 2014-09-18 19:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (121 votes), past polls