Tricky Perl Quine

Nota Lane: Conheci hoje no Twitter muito engraçado, à primeira vista, um tópico. E então ele olhou mais de perto e percebeu que não era apenas engraçado, mas também divertido. E já que hoje é sexta-feira, decidi que valia a pena compartilhar as descobertas com meus camaradas :)

imagem

Salve o seguinte programa em /tmp/quine.pl

Illegal division by zero at /tmp/quine.pl line 1. 

Execute-o com o comando

 perl /tmp/quine.pl 

e ela exibirá seu próprio código.

Os truques de tremor são bastante fáceis de compor em muitas linguagens de programação, onde um erro de sintaxe na fonte provoca um analisador para gerar um erro que coincidiria com o código fonte do programa. Publiquei vários desses truques no Twitter , incluindo o seguinte:

  File "quine.py", line 1 File "quine.py", line 1 ^ IndentationError: unexpected indent 

Mas a cevada no início deste artigo é um truque de um tipo completamente diferente - o programa entende corretamente . E não funciona por muito tempo, até tropeçar no erro de divisão por zero. Esse quine é muito sensível à nomeação de arquivos - por exemplo, executar ./quine.pl não funcionará.

Portanto, essa mensagem de erro é realmente o programa inteiro ?!

Este programa usa muito o analisador de barra de pérola, o que eu quero dizer.

O símbolo / é muito dependente do contexto do aplicativo e pode ser considerado como um símbolo de divisão ou como o início de uma expressão regular. E mesmo pequenas alterações no código deste programa levam a um erro na análise da regularidade e não na execução do código. Nesse caso, os dois caracteres aparecem no contexto do operador.

Outras partes que não são de dicionário deste programa são 1. , que é interpretado simplesmente como um número e . que é um operador de concatenação.

Então, o que as palavras significam?

Palavras em Perl podem ser nomes de rotinas, métodos, pacotes ou classes. Ou (no modo preguiçoso) linhas sem separador ou talvez algo mais que eu tenha esquecido!

O Perl também usa uma sintaxe incomum de chamada de método chamada "sintaxe indireta de objetos ", que se parece com isso:


na maioria das vezes você pode ver como

 print $filehandle "message"; my $instance = new Class(args); 

embora para Perl, a seguinte sintaxe seja preferível:

 $filehandle->print("message"); my $instance = Class->new(args); 

A documentação do perlobj diz:

O Perl usa heurística para analisar esse código, com base em quais nomes de pacotes ele conhece, quais sub-rotinas existem no pacote atual, quais palavras foram encontradas antes e analisando outros dados de entrada. Escusado será dizer que a heurística pode produzir resultados muito inesperados!
Como ele analisa esse código?
Começando pelo lado direito

 pl line 1. 

analisado como uma chamada de método

 line->pl(1.) 

onde line é o nome do pacote (classe) e pl é o método

No meio, "at", "tmp" e "quine" são analisados ​​como palavras simples, ou seja, cordas. A expressão é analisada da seguinte maneira:

 (("at" / "tmp") / "quine") . line->pl(1.) 

À esquerda, há duas chamadas de método indiretas dobradas,

 division->Illegal(zero->by( ... )) 

A expressão interna executada primeiro é:

 "at" / "tmp" 

E isso causa instantaneamente a divisão por zero exceção.

Source: https://habr.com/ru/post/pt446958/


All Articles