Categories

Posts in this category

Sun, 30 Aug 2009

Dissecting the "Starry obfu"


Permanent link

I've been asked a few times how the starry obfu works. Here it is again in all it's *cough* glory:

<(*+*)*(*+* +*/*) **** ** * * *+*+*/* **** ** * *
*+*-*/* **** ** * * *+* ****-* **** ** * * *-(*-*/
*) ** (*+*/*) **** ** * * *-* **** ** * * *-*+*/*
**** ** * * *+* **** ** * * *-* * * ***((* - */*)
** * * *-*/*) * * **** ** * * *+*/* ****-* ***(*-*
/*)**(*+*/*) * * ***((*-*/*)** * * *-*/*) * * ****
** * * *+*/* **** ** * * *+*+*/*-* * *>.split(<***
>).map: {eval("(* ** *+*+*-*/*+$_)(<* * *>)").chr\
.print}

This first character is a >, which introduces a list quote: <a b c> is the same as ("a", "b", "c"). This quote covers the first six and three quarter of the sevenths line.

It is later then used a string (by calling .split on it, and as such stringifies with spaces between the items. So it's roughly the same as "..." in this context.

Then comes a fairly trivial part: the string is split on ***, and via map a transformation is applied to to each item: it is interpolated into a string, which is eval'ed. The result is taken as a Unicode codepoint number, and printed to the screen.

To find out what exactly is evaled, you can replace the code inside the map to read something like this:

<(*+*)*(*+* +*/*) **** ** * * *+*+*/* **** ** * *
... 
>.map: { say("(* ** *+*+*-*/*+$_)(<* * *>)") };

The output begins with

(* ** *+*+*-*/*+(*+*)*(*+* +*/*) )(<* * *>)
(* ** *+*+*-*/*+* ** * * *+*+*/* )(<* * *>)

You might ask yourself "how on earth is this valid Perl code?"

The answer is quite simple: a single star can be either a term or an operator in Perl 6. As an infix operator it is simply multiplication. As a term it does magic: It constructs a closure which takes one positional argument, and puts that everywhere where a * appears as a term within that expression.

The reason is to make things like @array[*-1] work: it creates a closure { $_ - 1 } which is passed on to the array, which in turn passes the number of items in that array to closure, making @array[*-1] return the last array item.

So by the same token * ** *+*+*-*/*+(*+*)*(*+* +*/*) is internally transformed to

{ $_ ** $_ + $_ + $_ - $_ / $_ + ($_ + $_ ) * ($_ + $_ + $_/ $_) }

The (<* * *>) behind it invokes that closure with a list consisting of three items. In numerical context that becomes just the number 3, so the above translates to 3**3 + 3 + 3 - 3/3 + (3+3) * (3 + 3 + 3/3), evaluated 74 - the Unicode codepoint (and at the same time ASCII code) for the letter capital J.

It works similarly for all other letters; mystery lifted.

[/perl-6] Permanent link