[Moscow.pm] get own source code

Maxim Vuets maxim.vuets на gmail.com
Пн Мар 30 03:46:39 PDT 2015


2015-03-30 10:43 GMT+02:00 PEF Secure <pef-secure на yandex.ru>:
>> Боюсь, что это весьма хрупкое утверждение.
>>
>>     $ perl -e 'eval `cat code-reuse.txt`';
>>     lolwat?
>
> perl -le 'eval "blabla++"; print $@'
> Can't modify constant item in postincrement (++) at (eval 1) line 1, near
> "blabla++"
>
> *line 1* -- моё утверждение опирается на то, что эта информация всегда
> присутствует в тексте ошибки.

Да, вы правы. Я ошибочно полагал, что доступен только номер строки с eval-ом.

Но мы отошли от первоначального вопроса. При помощи этого примера я
хотел показать, что иметь номер строки помогает не сильно, поскольку
код может генериться на лету как угодно. И так мы снова вернулись к
оригинальной проблеме: узнать какой именно код был скомпилирован.

Короче, пока я отвечал, мне пришла в голову ещё одна мысль: отладчик.
Судя по всему, ему доступна вся информация, что вас интересует. Значит
и вы как-то можете сохранить её или получить к ней доступ.

Дано: код, который в рантайме компилирует динамически-созданный код.

    $ cat debugme.pl
    use v5.20;
    use warnings;

    sub mk_env_accessor {
        my $field = quotemeta $_[0];
        my $code = eval <<"CODE_END";
        sub {
            my \$field = '$field';
            my \$value = \$ENV{\$field};
            return \$value;
        };
    CODE_END
        die if $@;
        return $code;
    }

    my $get_user = mk_env_accessor('USER');
    say $get_user->();

Запускаю из отладчика:

    $ perl -d debugme.pl

    Loading DB routines from perl5db.pl version 1.44
    Editor support available.

    Enter h or 'h h' for help, or 'man perldebug' for more help.

    main::(debugme.pl:17):    my $get_user = mk_env_accessor('USER');
      DB<1> n
    main::(debugme.pl:18):    say $get_user->();
      DB<1> p $get_user
    CODE(0xec2cc0)
      DB<2> s
    main::CODE(0xec2cc0)((eval 8)[debugme.pl:6]:2):
    2:                my $field = 'USER';
      DB<2> s
    main::CODE(0xec2cc0)((eval 8)[debugme.pl:6]:3):
    3:                my $value = $ENV{$field};
      DB<2> s
    main::CODE(0xec2cc0)((eval 8)[debugme.pl:6]:4):
    4:                return $value;
      DB<2> s
    mvuets

Видите? Он прошёл по функции, которая была за-eval-ена из строки как
по родной. Возможно, это вдохновит вас на нахождение решение.


Подробная информация о списке рассылки Moscow-pm