Дело было вечером, echo «было нечего»

    Добрый день хабр. В статье я расскажу, как используя синтаксис php, можно написать функцию для вывода переданной ей строковой переменной, не использующую в своем теле символы «a-zA-Z0-9<>?»

    Вообще на хабре уже проскальзывали ссылки на статьи об использовании undefined variable, так что ничего нового я скорее всего не открою.


    В php, как и в любом языке с динамической типизацией, есть моменты скрытые от конечного разработчика, на них мы и сыграем.

    Начнем с конца. Мы всегда можем обратится к любому callable- была бы строка для вызова. Функции из SPL не исключение, хоть это и крайне редко применяется.
    $v="print_r";
    $v([1,2,3,4]);
    

    Array
    (
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    )

    Но обратится таким способом ни к echo ни к print мы не можем, ибо они являются конструкциями языка, а не функциями. Можно было бы использовать printf например, но мне такой подход не понравился. Поэтому мы будем использовать для вывода функцию assert.
    assert("print someShit");
    

    Кстати заменить print на echo в выражении выше не выйдет, они оба не функции, но print хотя бы старается таковой казаться.

    Строку для вывода нам передадут при вызове. Осталось самая малость. Получить строки «assert» и «print» используя доступный нам набор символов.

    Для этого мы используем ряд особенностей языка.
    1) В php мы можем обратится к undefined variable через _ (underscore). Нетрудно добится сужения типа и получить 0
    var_dump(+_);
    

    int(0)
    2) При приведении массива к строке, он будет преобразован в строку со значением Array
    //инициализируем пустой массив
    $_[]++;
    // В данном случае _ приводится к строке "_"
    $_[]=$_._;
    var_dump($_);
    

    array(2) {
    [0]=>
    int(1)
    [1]=>
    string(6) "Array_"
    }

    3) Как и в большинстве других языков, строка фактически является массивом символов. Символы можно инкрементировать.

    Скомбинировав все вышеперечисленное получаем такой код.

    <?
    error_reporting(E_ALL^E_NOTICE);
    crazyOutput("было нечего");
    
    function crazyOutput($__________){
    $_[]++;
    $_[]=$_._;
    $_=$_[$_[+_]];
    $___=$__=$_[++$__[]];
    $____=$_=$_[+_];
    $_++;$_++;$_++;
    $_=$____.++$___.$___.++$_.$__.++$___;
    $__=+_;$__=++$__+(++$__);
    $____=$_[$__];
    $____++;$____++;$____++;
    $______=$____;
    $____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;
    $___=$____;
    $____++;$____++;
    $______++;
    $___.=$____.$______;
    $______++;$______++;$______++;$______++;$______++;
    $___.=$______;
    $__=+_;$__++;
    $______=$___[$__];
    $______++;$______++;
    $___.=$______;
    $_($___." '".$__________."'");
    }
    ?>
    


    /usr/bin/php /var/www/garbage/brainfuck.php
    было нечего
    Process finished with exit code 0


    Практической пользы 0 в принципе… но что-то в этом есть =)

    P.S Рекомендуется к прочтению
    http://insert-script.blogspot.co.uk/2012/12/php-non-alpha-numeric-76-chars.html

    http://www.thespanner.co.uk/2012/08/21/php-nonalpha-tutorial/
    Метки:
    Поделиться публикацией
    Похожие публикации
    Комментарии 21
    • +32
      «Жениться тебе надо, барин» (с)

      А в общем затейно, мне понравилось.
    • +4
      Было бы здорово, если бы без нотисов ;-)
      • +8
        Мои пять копеек

        <?
        error_reporting(E_ALL^E_NOTICE);
        crazyOutput("hello world");
        
        function crazyOutput($ы) {
            $ю = ~ЏЌ–‘‹™;
            $ю(~ЪЊ, $ы);
        }
        ?>
        


        Раскурите? :)

        Кодировка — cp1251
        • +3
          ~ЏЌ–‘‹™ = ~<8f><8d><96><91><8b><99>
          ~0x8f = 'p'
          ~0x8d = 'r'
          ~0x96 = 'i'
          ~0x91 = 'n'
          ~0x8b = 't'
          ~0x99 = 'f'

          ~ЪЊ = "%s"
        • +4
          /me ощутил отчётливый запах Brainfuck…
          UPD: упс, не заметил…
          • +1
            Вы сами это придумали? Очень похоже на www.thespanner.co.uk/2012/12/13/tweetable-php-non-alpha/
            • +1
              К сожалению я не так крут — первоначально прочитал эту статью. Оттуда уже перешел на указанный вами материал. собственно формирование assErt взял оттуда. Меня смущало присутствие символов в конечном коде =)
              • 0
                Но и Вы без кавычек не обошлись )
                • +1
                  можно без кавычек запросто — call_user_func_array и printf, например. Только «брейнфака» с постинкрементами будет ОЧЕНЬ много :)
            • +8
              программа из одной строчки ни Perl
              помогите, пожалуйста исправить такую программу:

              cat «test… test… test...» | perl -e '$??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`{;;y; -/:-@[-`{-};`-{/" -;;s;;$_;see'

              — не печатает

              anonymous (25.09.2003 8:46:28)

              www.linux.org.ru/forum/development/392747
              10 лет прошло почти
              • +1
                Ниже в треде: «потому что ты лох, потому и не печатает :) надо перед рекурсивным входом и удалением всех директорий один слеш убрать :) ЛОХ :)»

                И как я понял по треду, он прав!
                • 0
                  UPD: не понял сразу — бред смолол
              • 0
                В php мы можем обратится к undefined variable через _ (underscore).

                А почему именно underscore? Поясните пожалуйста или дайте ссылку на соответствующий раздел в документации
                • +1
                  Такое же имя переменной, как любое другое. Ничего особенного в _ нет, кроме экзотического вида. Любая переменная не определена, пока её не определят, и _ точно так же.
                • –1
                  Практической пользы 0, стиль написания на высоте…
                  • +3
                    Тогда Вам не стоит заходить в записи из блога «Ненормальное программирование», там практичность не всегда преследуется авторами.
                  • +2
                    Новогодние праздники затянулись…
                      • 0
                        А если набирать имена переменных через зажатый Alt + 0160, то получим «невидимый» символ. Он отображается как обычный пробел, но является разрешенным для именования переменных. Выходит можем писать такой вот головокружительный код:

                        $  = 1;
                        $  = 2;
                        var_dump($  + $  );
                        
                        • 0
                          в юникоде разных пробелов штук 10 наберется ;)

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.