1989 schrieben Felix Lee, John Hayes und Angela Thomas einen Hacker-Test in Form eines Quiz mit vielen Insider-Witzen: „ Isst du Schleimpilze? "
Ich überlege mir folgende serie:
0015 Ever change the value of 4?
0016 ... Unintentionally?
0017 ... In a language other than Fortran?
Gibt es eine bestimmte Anekdote, die die Zahl „4“ in der Serie besonders macht?
Konnte bei einigen Fortran-Implementierungen der Wert von Konstanten geändert werden? War dies in anderen damals gebräuchlichen Sprachen möglich?
4
für5
in den internierten ganzen Zahlen - Listen.4 = 5
war möglich.Antworten:
In den alten Tagen (1970er und früher) hatten einige Computer keine MMU (und dies gilt heute für sehr billige Mikrocontroller).
Auf solchen Systemen gibt es keinen Speicherschutz, so dass kein Nur-Lese-Segment im Adressraum vorhanden ist und ein fehlerhaftes Programm eine Konstante überschreiben kann (entweder im Datenspeicher oder sogar im Maschinencode).
Die damaligen Fortran-Compiler führten formelle Argumente als Referenz durch . Wenn Sie dies getan haben
CALL FUN(4)
und sich derSUBROUTINE FUN(I)
Körper von geändert hat,I
z. B. mit einer AussageI = I + 1
im Körper, könnte es zu einer Katastrophe kommen, bei der der Anrufer von 4 zu 5 wechselt (oder noch schlimmer).Dies galt auch für die ersten Mikrocomputer wie den ursprünglichen IBM PC AT von 1984 mit MS-DOS
FWIW, ich bin alt genug, um als Teenager Anfang der 1970er Jahre solche Computer zu benutzen: IBM1620 und CAB500 (in einem Museum: das sind Computer aus den 1960er Jahren!). Der IBM1620 hat Spaß gemacht: Er wurde in Speichertabellen für Additionen und Multiplikationen verwendet (und wenn Sie diese Tabellen überschrieben, kam es zu Chaos). Sie könnten also nicht nur eine 4 überschreiben, sondern auch jede zukünftige 2 + 2-Addition oder 7 * 8-Multiplikation (aber ich habe diese schmutzigen Details wirklich vergessen und könnte daher falsch sein).
Heute könnten Sie den BIOS-Code im Flash-Speicher überschreiben, wenn Sie ausdauernd genug sind. Leider finde ich das nicht mehr lustig, also habe ich es nie versucht. (Ich habe sogar Angst, LinuxBios auf meinem Motherboard zu installieren).
Wenn auf aktuellen Computern und Betriebssystemen eine Konstante als Referenz übergeben und in der Aufgerufenen geändert wird, tritt lediglich eine Segmentierungsverletzung auf , die vielen C- oder C ++ - Entwicklern geläufig ist.
Übrigens: Nicht auswählen: Das Überschreiben von 4 ist keine Frage der Sprache, sondern der Implementierung.
quelle
gfortran
. Konstanten werden in ihr Segment eingefügt und als Referenz an ein Unterprogramm übergeben. Standardmäßig ist der konstante Abschnitt schreibgeschützt, sodass ein Speicherschutzfehler das Programm beendet.Dies war ein unbeabsichtigter Nebeneffekt der Funktionsaufruf-Bewertungsstrategie von FORTRAN in Kombination mit einer fehlerhaften Compiler-Optimierung.
FORTRAN II führte benutzerdefinierte Funktionen und Unterprogramme mit ihren als Referenz übergebenen Argumenten ein . (Ich weiß nicht, warum. Es war wahrscheinlich effizienter als die Weitergabe von Werten auf IBM-Hardware der Zeit.)
Normalerweise bedeutet Referenzübergabe, dass Sie einen l-Wert (wie eine Variable) anstelle eines r-Werts übergeben müssen. Die Designer von FORTRAN haben sich jedoch dazu entschlossen, hilfreich zu sein und Sie trotzdem r-Werte als Argumente übergeben zu lassen. Der Compiler generiert automatisch eine Variable für Sie. Also, wenn Sie geschrieben haben:
Der Compiler würde dies hinter den Kulissen in so etwas wie konvertieren
Es gab auch eine allgemeine Compiler-Optimierung, die als "Literal-Pool" bezeichnet wurde und mehrere Instanzen derselben numerischen Konstante in derselben automatisch generierten Variablen zusammenfasste. (Einige Sprachen in der C-Familie erfordern dies für Zeichenkettenliterale.) Also, wenn Sie geschrieben haben
Dies würde so behandelt, als ob es wäre
Das scheint eine vernünftige Sache zu sein, bis Sie ein Unterprogramm haben, das den Wert seiner Parameter ändert.
Boom!
CALL SUBBAR(4)
änderte den Wert der 4 im Literal-Pool in eine 5. Und dann wundern Sie sich, warumSUBBAZ
Sie davon ausgehen, dass Sie eine 5 statt der4
tatsächlich im Code geschriebenen übergeben haben.Neuere Versionen von Fortran verringern dieses Problem, indem Sie
INTENT
eine Variable alsIN
oder deklarierenOUT
und einen Fehler (oder zumindest eine Warnung) ausgeben, wenn Sie eine Konstante alsOUT
Parameter übergeben.quelle
Wenn eine Konstante in FORTRAN an eine andere Prozedur übergeben wird, ist sie nicht mehr geschützt. Darauf beziehen sie sich. Andere beliebte Programmiersprachen in der gleichen Zeit waren C und Pascal, die dieses Problem nicht hatten (und immer noch nicht hatten). Vielleicht gibt es ältere Programmiersprachen, von denen ich nicht weiß, dass sie dasselbe Problem haben.
quelle
.rodata
schreibgeschützten Segment befindet (wie es aktuelle Compiler tun), ändert es die Konstante nicht, würde aber eine SEGV verursachen.