Phát hiện nếu chương trình của bạn đã bị đột biến


16

Viết chương trình kết thúc mà không có lỗi.

Nếu bất kỳ byte đơn nào được thay thế bởi bất kỳ byte nào khác, chương trình sẽ xuất ra

CORRUPTED
  • Không đọc mã nguồn của bạn từ một tập tin
  • Chương trình của bạn không được tạo ra bất kỳ đầu ra nào khác

Đây là vì vậy câu trả lời ngắn nhất bằng byte sẽ thắng.

Chỉnh sửa: đã xóa yêu cầu "KHÔNG ĐÚNG"


làm cứng bức xạ có một loạt các câu hỏi tương tự, nhưng tôi không tìm thấy câu hỏi nào giống như câu hỏi này.
FryAmTheEggman

7
Đối với những người downvoters: Tôi nghi ngờ điều này là có thể (nếu rất khó), nếu bạn chọn đúng ngôn ngữ. Vui lòng không đóng hoặc xóa câu hỏi trừ khi bạn nghĩ có vấn đề gì đó ngoài việc không thể.

7
Điều gì đã thay đổi có ý nghĩa? Thay thế bởi một byte khác?
Dennis

4
@ ais523 FWIW Tôi đã đánh giá thấp thử thách bởi vì nó dường như được viết vội vàng, không phải vì tôi nghĩ nó quá khó.
Dennis

5
Không có gì là không rõ ràng, nhưng nó có thể được làm rõ ràng hơn . Bạn có thể làm rõ nếu cần một chương trình đầy đủ , thêm chương trình ví dụ và minh họa tất cả các sửa đổi có thể, đề cập đến việc thay thế một byte sẽ ảnh hưởng đến tệp được mã hóa UTF-8 như thế nào, thêm tập lệnh có thể được sử dụng để kiểm tra đệ trình, đề cập rằng chương trình không nên nhận đầu vào, v.v.
Dennis

Câu trả lời:


30

Cây lê , 76 byte

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

Chương trình này chứa một vài octet đi lạc không hợp lệ UTF-8. Như vậy, nó được hiển thị như trong Windows-1252. (Theo mặc định, nếu Cây lê nhìn thấy một octet không phải ASCII trong một chuỗi ký tự hoặc giống như nó coi nó như một đối tượng mờ đục và không cố gắng hiểu nó ngoài việc nhận thức được mã ký tự của nó là gì; hành vi này có thể là đã thay đổi thông qua một khai báo mã hóa nhưng chương trình không có. Vì vậy, chương trình này nằm trong "bộ ký tự tương thích ASCII không xác định".

Giải trình

Cây lê kiểm tra chương trình, tìm kiếm chuỗi con dài nhất có CRC-32 00000000. (Nếu có một chiếc cà vạt, nó sẽ chọn quãng tám trước.) Sau đó, chương trình sẽ được xoay để đặt nó vào lúc bắt đầu. Cuối cùng, chương trình được hiểu là một ngôn ngữ gần như là siêu ngôn ngữ của Perl, xác định một vài điều không xác định trong Perl để hoạt động giống như trong Python (và với một vài thay đổi nhỏ, ví dụ như printin một dòng mới cuối cùng trong A Pear Tree nhưng không ở Perl). Cơ chế này (và toàn bộ ngôn ngữ) được thiết kế cho các vấn đề ; Đây không phải là cái trước, nhưng nó chắc chắn là cái sau.

Trong chương trình này, chúng tôi có hai chuỗi con đáng chú ý mà CRC-32 tới 00000000; toàn bộ chương trình thực hiện, và nó cũng vậy print"$@CORRUPTED"__DATA__ =®®(xuất hiện hai lần). Như vậy, nếu chương trình không được sửa chữa, nó sẽ được đặt $@thành NOT và sau đó in nó theo sau CORRUPTED. Nếu chương trình bị hỏng, thì toàn bộ CRC-32 của chương trình sẽ không khớp, nhưng một trong những phần ngắn hơn sẽ vẫn chưa được sửa chữa. Bất cứ cái nào được quay vào đầu chương trình sẽ chỉ in CORRUPTED, như $@là chuỗi null.

Khi chuỗi đã được in, __DATA__được sử dụng để ngăn phần còn lại của chương trình chạy. (Tôi nghĩ rằng việc viết này __END__có thể được sử dụng thay thế, điều này rõ ràng sẽ tiết kiệm được hai byte. Nhưng tôi cũng có thể đăng phiên bản này ngay bây giờ, vì tôi đã dành rất nhiều thời gian để xác minh nó, và một phiên bản sửa đổi sẽ phải xác minh lại do những thay đổi của CRC và tôi chưa nỗ lực rất nhiều để đánh golf "tải trọng", vì vậy tôi muốn xem có ai có những cải tiến khác trong các nhận xét mà tôi có thể kết hợp cùng một lúc không. Lưu ý rằng #không hoạt động trong trường hợp một nhân vật bị hỏng trong một dòng mới.)

Bạn có thể tự hỏi làm thế nào tôi quản lý để kiểm soát CRC-32 trong mã của tôi ngay từ đầu. Đây là một mẹo toán học khá đơn giản dựa trên cách xác định CRC-32: bạn lấy CRC-32 của mã, viết nó theo thứ tự cuối nhỏ (ngược lại với thứ tự byte thường được sử dụng trong tính toán CRC-32 chương trình) và XOR với 9D 0A D9 6D. Sau đó, bạn thêm nó vào chương trình và bạn sẽ có một chương trình có CRC-32 bằng 0. (Ví dụ đơn giản nhất có thể, chuỗi null có CRC-32 là 0, do đó 9D 0A D9 6Dcũng có CRC-32 là 0 .)

xác minh

Cây lê có thể xử lý hầu hết các loại đột biến, nhưng tôi cho rằng "đã thay đổi" có nghĩa là "được thay thế bằng một octet tùy ý". Về mặt lý thuyết là có thể (mặc dù không có khả năng trong một chương trình ngắn) rằng có thể xảy ra xung đột băm ở đâu đó dẫn đến chương trình chạy sai, vì vậy tôi phải kiểm tra thông qua lực lượng vũ trang rằng tất cả các thay thế octet có thể sẽ khiến chương trình hoạt động chính xác. Đây là tập lệnh xác minh (được viết bằng Perl) mà tôi đã sử dụng:

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

Một n -bit CRC sẽ phát hiện bất kỳ lỗi đơn bật không dài hơn n bit. Va chạm băm là không thể trong trường hợp cụ thể, không cần xác minh vũ lực.
Rainer P.

@RainerP.: Tôi biết rằng một đột biến sẽ ngăn CRC cho các phần ban đầu có CRC bằng 0. Tuy nhiên, có khả năng nó có thể giới thiệu một chuỗi con mới của mã có CRC bằng 0; mục đích của vũ phu là để đảm bảo rằng điều đó đã không xảy ra.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.