$@='NOT ';print"$@CORRUPTED"__DATA__ =®®”print"$@CORRUPTED"__DATA__ =®®”Ê®›~
Questo programma contiene alcuni ottetti vaganti che non sono validi UTF-8. Come tale, viene mostrato come appare in Windows-1252. (Per impostazione predefinita, se A Pear Tree vede un ottetto non ASCII in una stringa letterale o simile, lo tratta come un oggetto opaco e non cerca di capirlo oltre a essere consapevole di quale sia il suo codice carattere; questo comportamento può essere modificato tramite una dichiarazione di codifica ma il programma non ne ha uno. Quindi il programma è logicamente in "set di caratteri ASCII non specificato". Tutti gli ottetti non ASCII sono comunque nei commenti, quindi non importa.)
Spiegazione
A Pear Tree controlla il programma, cercando la sottostringa più lunga che abbia un CRC-32 di 00000000
. (Se c'è un pareggio, seleziona prima l'ottetbetico.) Quindi il programma viene ruotato per metterlo all'inizio. Infine, il programma viene interpretato come un linguaggio che è quasi un superset di Perl, definendo alcune cose che non sono definite in Perl per funzionare allo stesso modo di in Python (e con alcune piccole modifiche, ad esempio print
stampa una nuova riga finale in A Pear Tree ma non in Perl). Questo meccanismo (e il linguaggio nel suo insieme) è stato progettato per problemi di poliglotta e di indurimento delle radiazioni ; questo non è il primo, ma è sicuramente il secondo.
In questo programma, abbiamo due notevoli sottostringhe a cui CRC-32 00000000
; l'intero programma lo fa, e così fa print"$@CORRUPTED"__DATA__ =®®
da solo (che appare due volte). Pertanto, se il programma non è danneggiato, verrà impostato $@
su NOT
e quindi lo stampa seguito da CORRUPTED
. Se il programma è danneggiato, il CRC-32 del programma nel suo insieme non riuscirà a corrispondere, ma una delle sezioni più brevi rimarrà non corrotta. Qualunque sia ruotato all'inizio del programma verrà stampato CORRUPTED
, così come $@
la stringa nulla.
Una volta stampata la stringa, __DATA__
viene utilizzata per impedire il resto del programma in esecuzione. (Mi viene in mente di scrivere questo che __END__
potrebbe essere usato invece, il che salverebbe chiaramente due byte. Ma potrei anche pubblicare questa versione ora, perché ho trascorso un sacco di tempo a verificarlo, e una versione modificata dovrebbe essere ricontrollato a causa delle modifiche del CRC e non ho ancora fatto grandi sforzi nel golfare il "payload", quindi voglio vedere se qualcuno ha altri miglioramenti nei commenti che posso incorporare allo stesso tempo. Nota che #
non funziona nella situazione in cui un personaggio è corrotto in una nuova riga.)
Potresti chiederti come sono riuscito a controllare il CRC-32 del mio codice in primo luogo. Questo è un trucco matematico abbastanza semplice basato sul modo in cui è definito CRC-32: prendi il CRC-32 del codice, lo scrivi in ordine little-endian (il contrario dell'ordine dei byte che viene normalmente utilizzato dal calcolo CRC-32 programmi) e XOR con 9D 0A D9 6D
. Quindi lo aggiungi al programma e avrai un programma con un CRC-32 di 0. (Come l'esempio più semplice possibile, la stringa null ha un CRC-32 di 0, quindi 9D 0A D9 6D
ha anche un CRC-32 di 0 .)
Verifica
Un albero di pere può gestire la maggior parte delle mutazioni, ma suppongo che "cambiato" significhi "sostituito con un ottetto arbitrario". È teoricamente possibile (anche se improbabile in un programma così breve) che potrebbe esserci una collisione di hash da qualche parte che porta a un programma errato in esecuzione, quindi ho dovuto verificare con la forza bruta che tutte le possibili sostituzioni di ottetti avrebbero lasciato il programma funzionare correttamente. Ecco lo script di verifica (scritto in Perl) che ho usato:
use 5.010;
use IPC::Run qw/run/;
use warnings;
use strict;
undef $/;
$| = 1;
my $program = <>;
for my $x (0 .. (length $program - 1)) {
for my $a (0 .. 255) {
print "$x $a \r";
my $p = $program;
substr $p, $x, 1, chr $a;
$p eq $program and next;
alarm 4;
run [$^X, '-M5.010', 'apeartree.pl'], '<', \$p, '>', \my $out, '2>', \my $err;
if ($out ne "CORRUPTED\n") {
print "Failed mutating $x to $a\n";
print "Output: {{{\n$out}}}\n";
print "Errors: {{{\n$err}}}\n";
exit;
}
}
}
say "All OK! ";