|P is for Practical|
The Lighter Side of Perl Culture (Part III): Obfuby eyepopslikeamosquito (Canon)
|on Jan 23, 2005 at 06:15 UTC||Need Help??|
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.
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 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:
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.
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.
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:
Not bad for a first attempt! A bit more interesting than the first JAPH. ;-)
From the BooK archives, here are the earliest $A++s:
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++:
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).
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.
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.
An $A++ penned by the mtve:
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
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:
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.
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:
Other Articles in This Series