Détectez si votre programme a été muté

16

Écrivez un programme qui se termine sans erreur.

Si un seul octet est remplacé par un autre octet, le programme devrait sortir

CORRUPTED
  • Ne lisez pas votre code source à partir d'un fichier
  • Votre programme ne doit produire aucune autre sortie

Il s'agit de donc la réponse la plus courte en octets l'emporte.

Edit: supprimé « NOT CORROMPUE » exigence

noɥʇʎԀʎzɐɹƆ
la source
le durcissement par radiation a une foule de questions similaires, mais je n'en ai trouvé aucune qui ressemble à celle-ci.
FryAmTheEggman
7
Aux downvoters: je soupçonne que c'est possible (si c'est très difficile), si vous choisissez la bonne langue. Veuillez ne pas fermer ou supprimer la question à moins que vous ne pensiez qu'il y a quelque chose de mal autre que l'impossible.
7
Que signifie changé ? Remplacé par un autre octet?
Dennis
4
@ ais523 FWIW J'ai rétrogradé le défi parce qu'il semble écrit à la hâte, pas parce que je pense que c'est trop difficile.
Dennis
5
Ce n'est pas que quelque chose n'est pas clair, mais cela pourrait être plus clair . Vous pourriez clarifier si un programme complet est requis, ajouter un exemple de programme et illustrer toutes les modifications possibles, mentionner comment les substitutions à un octet affecteraient un fichier encodé en UTF-8, ajouter un script pouvant être utilisé pour tester les soumissions, mentionner que le programme ne doit pas prendre de commentaires, etc.
Dennis

Réponses:

30

Un poirier , 76 octets

$@='NOT ';print"$@CORRUPTED"__DATA__ =®®”print"$@CORRUPTED"__DATA__ =®®”Ê®›~

Ce programme contient quelques octets parasites qui ne sont pas valides UTF-8. En tant que tel, il est affiché tel qu'il apparaît dans Windows-1252. (Par défaut, si A Pear Tree voit un octet non ASCII dans un littéral de chaîne ou similaire, il le traite comme un objet opaque et n'essaie pas de le comprendre au-delà de la connaissance de son code de caractère; ce comportement peut être modifié via une déclaration d'encodage mais le programme n'en a pas. Le programme est donc logiquement dans "un jeu de caractères compatible ASCII non spécifié". Tous les octets non ASCII sont dans les commentaires de toute façon, donc cela n'a pas vraiment d'importance.)

Explication

Un poirier vérifie le programme, recherchant la plus longue sous-chaîne possédant un CRC-32 00000000. (S'il y a égalité, il choisit l'octetbétique en premier.) Ensuite, le programme est tourné pour le mettre au début. Enfin, le programme est interprété comme un langage qui est presque un surensemble de Perl, définissant quelques éléments qui ne sont pas définis en Perl pour fonctionner de la même manière qu'en Python (et avec quelques modifications mineures, par exemple, printimprime une nouvelle ligne finale dans A Pear Tree mais pas en Perl). Ce mécanisme (et le langage dans son ensemble) a été conçu pour le et le problèmes de ; ce n'est pas le premier, mais c'est définitivement le dernier.

Dans ce programme, nous avons deux sous-chaînes notables que CRC-32 00000000; tout le programme le fait, tout comme print"$@CORRUPTED"__DATA__ =®®lui-même (qui apparaît deux fois). En tant que tel, si le programme n'est pas corrompu, il sera défini $@sur NOT puis l'imprimera suivi de CORRUPTED. Si le programme est corrompu, le CRC-32 du programme dans son ensemble ne correspondra pas, mais l'une des sections les plus courtes ne sera pas corrompue. Celui qui est tourné au début du programme s'imprime CORRUPTED, tout $@comme la chaîne nulle.

Une fois la chaîne imprimée, __DATA__est utilisée pour empêcher l'exécution du reste du programme. (Cela me vient à l'esprit d'écrire ceci qui __END__pourrait être utilisé à la place, ce qui permettrait clairement d'économiser deux octets. Mais je peux aussi poster cette version maintenant, car j'ai passé beaucoup de temps à la vérifier, et une version modifiée devrait être revérifié en raison des modifications apportées au CRC, et je n'ai pas encore déployé beaucoup d'efforts pour jouer à la "charge utile", donc je veux voir si quelqu'un a d'autres améliorations dans les commentaires que je peux intégrer en même temps. Notez que #cela ne fonctionne pas dans le cas où un personnage est corrompu dans une nouvelle ligne.)

Vous vous demandez peut-être comment j'ai réussi à contrôler le CRC-32 de mon code en premier lieu. Ceci est une astuce mathématique assez simple basée sur la façon dont le CRC-32 est défini: vous prenez le CRC-32 du code, l'écrivez dans un ordre peu-endian (l'inverse de l'ordre des octets qui est normalement utilisé par le calcul du CRC-32 programmes) et XOR avec 9D 0A D9 6D. Ensuite, vous ajoutez cela au programme, et vous aurez un programme avec un CRC-32 de 0. (Comme l'exemple le plus simple possible, la chaîne nulle a un CRC-32 de 0, donc a 9D 0A D9 6Dégalement un CRC-32 de 0 .)

Vérification

Un poirier peut gérer la plupart des types de mutations, mais je suppose que «changé» signifie «remplacé par un octet arbitraire». Il est théoriquement possible (bien que peu probable dans un programme aussi court) qu'il puisse y avoir une collision de hachage quelque part qui conduise à un mauvais programme, donc j'ai dû vérifier par force brute que toutes les substitutions d'octets possibles laisseraient le programme fonctionner correctement. Voici le script de vérification (écrit en Perl) que j'ai utilisé:

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!    ";

la source
Un CRC à n bits détectera toute rafale d'erreur unique ne dépassant pas n bits. Les collisions de hachage sont impossibles dans le cas donné, il n'est pas nécessaire de vérifier la force brute.
Rainer P.
@RainerP.: Je suis conscient qu'une mutation empêchera le CRC pour les parties qui ont à l'origine un CRC de 0 correspondant. Cependant, il est possible qu'il puisse introduire une nouvelle sous-chaîne du code qui a un CRC de 0; le but du brute-forcing est de garantir que cela ne s'est pas produit.