Off-by-one-Error

Off-by-one-Error

Ein Off-By-One-Error (deutsch etwa Um-Eins-daneben-Fehler) oder ±1-Problem bezeichnet eine bestimmte Art von Programmierfehlern, die bei der Entwicklung von Software unterlaufen können und meist ein spezieller Fall des Zaunpfahlproblems, eines Logikproblems der Indizierung, sind. Bei einem Off-By-One-Fehler ist entweder die Größenangabe eines Speicherblocks um 1 falsch oder es kann bei maximaler Puffergröße um einen Schritt zu viel in den Speicher geschrieben werden, wobei der Speicher eines anderen Puffers bzw. einer Variable überschrieben wird.

Einen Off-by-one-Error macht ein Programmierer, wenn er im Umgang mit Datenfeldern, Arrays, Vektoren, Listen oder anderen indizierbaren Datentypen eine Kontrollstruktur (z. B. eine Schleife) auf solche Weise fehlerhaft gestaltet, dass sie entweder einmal zu oft oder einmal zu wenig durchlaufen wird.

Im Falle eines Off-by-one-Error wird typischerweise beim Schreiben der Schleife, die ein Feld verarbeiten soll, die Abbruch- bzw. Fortsetzungsbedingung falsch gewählt, so dass im Rumpf der Schleife eine Anweisung, die Index-basiert auf das Feld zugreift, genau einmal zu oft oder einmal zu wenig ausgeführt wird, wodurch entweder versucht wird, auf ein Element des Feldes zuzugreifen, das nicht existiert, oder das letzte (bzw. erste) Element des Feldes ausgelassen wird. Im erstgenannten Fall ist oft ein Index-Out-Of-upper-Range-Fehler (o. ä.) die auffällige Folge, im letztgenannten Fall wird mitunter gar kein Fehler sichtbar, solange nicht die gesamte Puffergröße genutzt werden soll oder ein Index-Out-Of-lower-Range-Fehler gemeldet wird.

Ein Off-By-One-Fehler kann durchaus zu einem Absturz des Programms führen, wenn im Speicher nach dem Puffer wichtige Daten liegen, die von der Schleife dann überschrieben werden (z. B. Zeiger auf eine Struktur). Grundsätzlich kann nach einem Puffer im Arbeitsspeicher auch Programmcode liegen, wobei in der Regel ein zufälliges Überschreiben ebenfalls einen Programmabsturz verursacht, da die Daten keinem gültigen Maschinenbefehl entsprechen. Hingegen ist eine Speicherschutzverletzung sehr unwahrscheinlich, da Betriebssysteme Arbeitsspeicher in großen Blöcken reservieren. Eine Ausnutzung eines Off-By-One-Fehlers für Exploits ist kaum denkbar, da hierzu zufälligerweise viele Bedingungen gleichzeitig erfüllt sein müssen.

Ursächlich für Off-By-One-Fehler ist meistens der Umstand, dass man bei der Programmierung das Zählen bei 0 beginnt und nicht mit 1. Bei einer Feldvariablen mit 10 Feldern bedeutet das, dass das letzte Feld den Index 9 hat und nicht 10. Eine weitere Fehlerquelle ist die sehr häufige Verwendung des so genannten Nullbytes, vor allem bei Zeichenketten, also Text. Das Nullbyte ist ein in Text nicht vorkommendes Zeichen mit dem Wert 0 und markiert das Ende einer Zeichenkette, während der eigentliche Puffer für die Zeichenkette um ein Vielfaches größer sein kann. Dadurch muss man bei variablen Pufferinhalten die Puffergröße nicht ständig verändern und ebenso die Länge der Zeichenkette nicht separat angeben.

Durch das Nullbyte ist eine Zeichenkette allerdings prinzipiell um ein Zeichen länger, als die Zeichenkette an sich lang ist. Beispielsweise ist die Zeichenkette „Hallo“ somit zwar 5 Zeichen lang, benötigt aber 6 Zeichen im Speicher. Funktionen, die die Länge einer Zeichenkette ermitteln und zurückgeben, zählen das Nullbyte nicht mit.

Off-By-One-Fehler können leicht unterlaufen und sind sehr schwer zu finden, vor allem, da sie sich sehr häufig nur unter ganz speziellen Bedingungen bemerkbar machen. Auch bei der Durchsicht des Quelltextes können sie sehr leicht übersehen werden. Erschwerend kommt hinzu, dass Indizes oder Offsets im Quelltext meist durch Variablen oder Formeln gebildet werden. Maßnahmen von Compiler/Interpreter oder ggf. Betriebssystemen, die ein Überschreiten einer Puffergrenze um jedes einzelne Byte registrieren, greifen auch nur in dem Spezialfall, dass der gesamte reservierte Puffer genutzt werden soll.

Beispiele

Beispiel aus der Sprache C:

 int nettopreise[10];
 int i;
 
 /* nettopreise initialisieren */
 ...
 
 for (i = 0; i <= 10; ++i)
     nettopreise[i] = nettopreise[i] * 1.19; // MWSt aufschlagen.

In diesem Fall müsste es i < 10 und nicht i <= 10 heißen, da in der Deklaration zwar 10 als Feldgröße angegeben wurde, aber aufgrund der Nullbasiertheit von C der maximale Index 9 ist.

Häufig resultiert diese Art der Fehler aus der Verwirrung, die dadurch entsteht, dass Menschen von 1 bis N zählen, Feldindizes in vielen Programmiersprachen aber von 0 bis N−1 gehen. Dann gibt es auch noch das Größer-Als-Zeichen und das Größer-Gleich-Zeichen, die man verwechseln kann. Darüber hinaus ist die Abbruchbedingung auch öfters mal etwas komplizierter, so dass man als Mensch eben einfach mal daneben liegt, und zwar meistens um genau 1.

Besonders tückisch ist der Fall einer Datenstruktur, die eben doch mit 1 beginnt, wenn Schleifenzählungen über diese Datenstruktur aber mit 0 beginnen.

Beispiel aus der Sprache C:

 const int anzahlPreise;
 int nettopreise[anzahlPreise];
 int i;
 int startPos; // Position ist immer eins größer als Index.
 int anzahlZuVerarbeitenderPreise;
 
 for (i = startPos-1; startPos + anzahlZuVerarbeitenderPreise > i; ++i)
     nettopreise[i] = nettopreise[i] * 1.19; // MWSt aufschlagen.

Ebenfalls kann einem leicht ein Off-by-one-Error unterlaufen, wenn man bei Bereichsgrenzen nicht beachtet, ob die untere und obere Schranke einschließend oder ausschließend ist. So liefert die Funktion substring aus C und Java den Teil eines Strings, der die untere Schranke mit einschließt, die obere aber nicht.

Will man beispielsweise aus dem Wort "Foobar" das Teilwort "bar" herauslösen, indem man die Buchstaben durchzählt, so kann man sich bei der oberen Schranke leicht vertun, selbst wenn man korrekt bei 0 zu zählen beginnt. Da das Wort "bar" die Buchstaben bei den Indizes 3, 4 und 5 umfasst, ist man versucht, substring(3, 5) aufzurufen. Als Ergebnis würde man aber nur "ba" erhalten.


Wikimedia Foundation.

Игры ⚽ Нужно решить контрольную?

Schlagen Sie auch in anderen Wörterbüchern nach:

  • Off-by-one error — An off by one error (OBOE) is a logical error involving the discrete equivalent of a boundary condition. It often occurs in computer programming when an iterative loop iterates one time too many or too few. Usually this problem arises when a… …   Wikipedia

  • Off-by-one error — Ein Off By One Error (deutsch etwa Um Eins daneben Fehler) oder +/ 1 Problem bezeichnet eine bestimmte Art von Programmierfehlern, die bei der Entwicklung von Software unterlaufen können und meist ein spezieller Fall des Zaunpfahlproblems, eines… …   Deutsch Wikipedia

  • off-by-one error — /ɒf baɪ ˈwʌn ɛrə/ (say of buy wun eruh) noun Computers a programming error which results in a repeated loop iterating once too often, frequently caused by the fact that the programmer fails to appreciate that the sequence has started at 0 rather… …  

  • Off-by-one — Ein Off By One Error (deutsch etwa Um Eins daneben Fehler) oder +/ 1 Problem bezeichnet eine bestimmte Art von Programmierfehlern, die bei der Entwicklung von Software unterlaufen können und meist ein spezieller Fall des Zaunpfahlproblems, eines… …   Deutsch Wikipedia

  • Off by one — Ein Off By One Error (deutsch etwa Um Eins daneben Fehler) oder +/ 1 Problem bezeichnet eine bestimmte Art von Programmierfehlern, die bei der Entwicklung von Software unterlaufen können und meist ein spezieller Fall des Zaunpfahlproblems, eines… …   Deutsch Wikipedia

  • One Ring — The One Ring is a fictional artifact that appears as the central plot element in J. R. R. Tolkien s Middle earth fantasy novels. It is described in an earlier story, The Hobbit (1937), as a magic ring of invisibility. The sequel The Lord of the… …   Wikipedia

  • one-off — ➔ one time * * * Ⅰ. one off UK US /ˌwʌnˈɒf/ adjective [before noun] UK ► (US one shot) produced or happening only once: »The London store is stocking 12 exclusive, one off designs. »a one off opportunity/chance »a …   Financial and business terms

  • One-Two-GO Airlines Flight 269 — Crash scene Accident summary Date September 16 2007 …   Wikipedia

  • off — off1 [ôf, äf] adv. [LME var. of of,OF1, later generalized for all occurrences of of in stressed positions] 1. so as to be or keep away, at a distance, to a side, etc. [to move off, to ward off] 2. so as to be measured, divided, etc. [to pace off …   English World dictionary

  • One of Us (ABBA song) — One of Us Single by ABBA from the album The Visitors B side …   Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”