boojeboy has asked for the wisdom of the Perl Monks concerning the following question:

Ok so I ran across this code in a job listing for Fonality:
#!/usr/bin/perl s; (?:SEEKING)?; PERLqny~%|fsyx%~tz&; ?$^X=~m.\w+$.:DEVELOPERS; s"$&"Ktsf"i; s^.^chr ord($&)-5^eg; $\=$/;print||" ;) "
Output: Fona If you add 'use strict;' it won't run... How can I begin to untangle this code?

Replies are listed 'Best First'.
Re: Obfusicated code
by kyle (Abbot) on Dec 15, 2007 at 20:32 UTC

    It can sometimes help to use B::Deparse:

    $ perl -MO=Deparse fonality.pl s/\n(?:SEEKING)?/\nPERLqny~%|fsyx%~tz&/ ? $^X =~ /\w+$/ : '???'; s/$&/Ktsf/i; s/./chr ord($&) - 5;/eg; $\ = $/; '???' unless print $_; fonality.pl syntax OK

    Let's pick it apart.

    s; (?:SEEKING)?; PERLqny~%|fsyx%~tz&;

    This is does nothing. It's a replacement on $_, which has the empty string in it. The replacement does nothing because it doesn't match the empty string because the empty string doesn't have a \n in it. It's worth knowing that it doesn't match because of what comes next:

    ?$^X=~m.\w+$.:DEVELOPERS;

    The question mark at the front uses the replacement (s///) as a condition, so the stuff after the question mark and leading up to the colon is not executed. DEVELOPERS is a bareword, which in this case will be interpreted as a string, which does nothing.

    s"$&"Ktsf"i;

    This is another replacement on $_. At this point, $& (aka $MATCH, if you use English, see perlvar) has nothing in it, and so does $_, so this matches. After the replacement, $_ eq 'Ktsf'.

    s^.^chr ord($&)-5^eg

    Here's another replacement. In this case, we're replacing every single character in $_ with the character that's five characters back on the ASCII chart. For example, chr ord('K') - 5 is 'F'. The /g flag is what makes this replace every character, and the /e flag is what makes it interpret the replacement expression as code instead of text. See chr and ord. After this, $_ eq 'Fona'

    $\=$/

    See perlvar for these. The output record separator is being set to the same value as the input record separator, which is still at its default, newline ("\n"). That is, $\="\n". This means that when you print something, it will have newline appended for you. That's convenient for the next part.

    print||" ;) "

    This prints the contents of $_, with $\ (newline) appended. Since print returns true on success, stuff after the || is not executed. Even if it were, it's a string, so it does nothing.

    I hope this explanation helps. I welcome further questions and corrections from my fellow monks.

Re: Obfusicated code
by poolpi (Hermit) on Dec 15, 2007 at 21:56 UTC
    In a first time you can simplify the obfuscated code like this :
    s//Ktsf/; # now $_ = 'Ktsf' s/./chr ord($&)-5/e; # $_ = 'Fona' $\=$/; # By default $/ is a newline # A newline is printed after the last print print # print $_ and a newline => "Fona\n"
    Second time :
    use strict; print map { chr ord($_) - 5 } ('K', 't', 's', 'f'); print "\n";
    Finaly :
    'K' ASCII code = 75
    'F' ASCII code = 70
    chr 70 eq 'F';)

    HTH,
    PooLPi
Re: Obfusicated code
by Anonymous Monk on Dec 15, 2007 at 22:25 UTC
    $ perl -le' print "1: $_"; s/(?:SEEKING)?/PERLqny~%|fsyx%~tz&/ ? $^X =~ /\w+$/ : DEVELOPERS; print "2: $_"; print "3: $&"; s/$&/Ktsf/i; print "4: $_"; s/./ chr ord( $& ) - 5 /eg; print "5: $_"; $\ = $/; print || " ;) " ' 1: 2: PERLqny~%|fsyx%~tz& 3: perl 4: Ktsfqny~%|fsyx%~tz& 5: Fonality wants you! Fonality wants you!