Bounds checking

Methode in der Informatik um sicherzustellen das eine Variable innerhalb bestimmter Grenzen ist, bevor sie genutzt wird

In der Programmierung ist Grenzüberprüfung oder bounds checking jede Methode, bei der überprüft wird, ob der Wert einer Variablen innerhalb bestimmter Grenzen ist, bevor sie verwendet wird. Diese Methoden werden normalerweise angewendet, um entweder zu überprüfen, dass eine Zahl den Wertebereich eines bestimmten Datentyps nicht überschreitet (Wertebereichsüberprüfung), oder dass eine Variable, die zum Indizieren eines Arrays verwendet wird, nicht außerhalb des Arrays zeigt (Indexüberprüfung). Ist die Variable nicht innerhalb der Grenzen, wird normalerweise eine Ausnahmebehandlung gestartet.

Da das Überprüfen der Grenzen oft zeitaufwendig ist, wird zum Beispiel bei der Optimierung von Compilern auf das Vermeiden von Grenzüberprüfung geachtet.

Wertebereichsüberprüfung

Bearbeiten

Bei der Wertebereichsüberprüfung wird darauf geachtet, dass eine Zahl innerhalb eines bestimmten Wertebereiches ist, zum Beispiel, dass eine Ganzzahl von einem 16-Bit-Ganzzahltypen aufgenommen werden kann. (z. B. Arithmetischer Überlauf). Dies ist nicht das gleiche wie Typenüberprüfung. Andere Wertebereiche sind in anderer Weise restriktiv. Wenn zum Beispiel eine Variable die Nummer eines Monats im Jahr speichern soll, dann darf sie nur die Zahlen von 1 bis 12 aufnehmen.

Indexüberprüfung

Bearbeiten

Bei der Indexüberprüfung werden bei allen Ausdrücken, bei denen in einem Array indiziert wird, der Index gegen die Grenzen des Arrays (die bei der Deklaration des Arrays festgelegt wurden) getestet. Wenn der Index nicht innerhalb der Grenzen ist, wird ein „Out-of-bounds“-Fehler ausgelöst. Das Lesen oder Schreiben außerhalb der Grenzen eines Arrays kann zu Fehlfunktionen und Abstürzen des Programms führen. Es kann auch zu einer Vielzahl von Sicherheitsrisiken (siehe auch Pufferüberlauf) führen, daher ist dynamische Indexüberprüfung eine gängige Praxis in vielen höheren Programmiersprachen.

Frühe Programmiersprachen mit Indexüberprüfung sind Algol 60, Algol 68 und Pascal (kompiliert), so wie auch die Skriptsprache BASIC.

Viele Programmiersprachen wie zum Beispiel C verwenden nie automatische Indexüberprüfungen, um die Laufzeit zu verringern. Dadurch bleiben viele Off-by-One-Fehler oder Pufferüberläufe unbemerkt. Es stellt sich die Frage, ob dies ein zu großes Opfer für die Beschleunigung der Programme ist.[1] Etablierte Programmiersprachen, die Laufzeitüberprüfung unterstützen, sind Ada, C#, Haskell, Java, JavaScript, Lisp, PHP, Python, Ruby, Rust, und Visual Basic. C++, D und OCaml haben Compiler switches, um Grenzüberprüfungen während der Laufzeit zu aktivieren. C# hat außerdem sogenannte „unsafe regions“. Das sind Sektionen des Codes, in dem für eine höhere Effizienz unter anderem keine Grenzüberprüfungen durchgeführt werden. Dadurch kann an besonders kritischen Stellen Zeit gewonnen werden, ohne das gesamte Programm zu gefährden.

Die JS++ Programmiersprache ist in der Lage mithilfe von „existent types“, einem nominellen Typ, der beschreibt, ob der Index innerhalb der Grenzen ist oder nicht, während der Kompilierung zu überprüfen, ob ein Index in den erlaubten Grenzen ist. Es hat sich gezeigt, dass „existent types“ die Kompilierzeit nur um 1 ms verlängern.[2]

Hardware bounds checking

Bearbeiten

Die Sicherheit, die durch Grenzüberprüfung hinzukommt, kostet CPU-Zeit, die allerdings wegfällt, wenn die Überprüfung nicht durch die Software, sondern durch Hardware durchgeführt wird. Eins der ersten Systeme mit Hardware bounds checking war das ICL 2900 Series Mainframe (angekündigt in 1974).[3]

Der VAX Computer hat einen INDEX Assembly-Befehl für Array-Indexüberprüfung der sechs Operanden akzeptiert, von denen alle jeden beliebigen VAX-Adressierungsmodus verwenden können. Der B6500 und auch Burroughs-Computer führten Grenzüberprüfungen durch, wenn eine Sprache verwendet wurde, die Assembly-Code erzeugte. Eine begrenzte Anzahl von CPUs haben später spezielle Befehle für Grenzüberprüfungen, z. B. der CHK2-Befehl für die Motorola 68000-Serie.

Seit 2005 gibt es Forschungen zu Methoden, um die integrierte virtuellen Speicherverwaltungseinheit von x86 für die Sicherheit von Array-Indizierung und Pufferzugriff zu erhöhen.[4] In 2015 brachte Intel die Erweiterung Intel MPX für ihre Skylake-Architektur auf den Markt, die die Grenzen in einem CPU-Register und einer Tabelle im Speicher nutzt. Seit 2017 werden MPX-Erweiterungen von GCC unterstützt.

Bearbeiten

Einzelnachweise

Bearbeiten
  1. C. Cowan, F. Wagle, F. Calton Pu, S. Beattie, J. Walpole: Proceedings DARPA Information Survivability Conference and Exposition. DISCEX'00. Band 2. IEEE, 1999, ISBN 978-0-7695-0490-2, Buffer overflows: Attacks and defenses for the vulnerability of the decade, S. 119–129, doi:10.1109/DISCEX.2000.821514 (englisch).
  2. JS++ 0.9.0: Efficient Compile Time Analysis of Out-of-Bounds Errors – JS++ Blog. Abgerufen am 7. November 2023 (englisch).
  3. J. K. Buckle: The ICL 2900 Series. Macmillan Computer Science Series, 1978, ISBN 978-0-333-21917-1, S. 17, 77 (englisch, fujitsu.com (Memento des Originals vom 20. April 2018 im Internet Archive) [abgerufen am 20. April 2018]).
  4. Lap-Chung Lam, Tzi-Cker Chiueh: 2005 International Conference on Dependable Systems and Networks (DSN'05). 2005, ISBN 0-7695-2282-3, Checking Array Bound Violation Using Segmentation Hardware, S. 388–397, doi:10.1109/DSN.2005.25 (englisch).