In C funktioniert die automatische Typumwandlung nach dem Prinzip der "üblichen arithmetischen Umwandlungen". Bei der Beteiligung an einem Ausdruck von Zahlen mit unterschiedlichem Vorzeichen (signed/unsigned) erfolgt die Umwandlung nach den folgenden Regeln:
Beispiel für gefährliche Arithmetik:
int a = -1; // signed unsigned int b = 1; printf("%d\n", a < b); // immer falsch, da a in ein sehr großes unsigned umgewandelt wird
Ergebnis: -1, das in unsigned umgewandelt wird, wird zu einer sehr großen positiven Zahl.
Wichtige Hinweise:
Frage: Welches Ergebnis gibt der Ausdruck (int)(unsigned)-1 zurück?
Erwartet falsche Antwort: "-1, denn -1 und wird zu int umgewandelt."
Richtige Antwort:
Im Ausdruck (unsigned)-1 erfolgt zuerst die Umwandlung von -1 zu unsigned (auf einer 32-Bit-Plattform ist dies 0xFFFFFFFF), dann zurück zu signed int, was ebenfalls von der Implementierung abhängt, aber oft wieder -1 ergibt (wenn two's complement verwendet wird). Es ist jedoch richtiger zu sagen: Das Ergebnis hängt von den Standards der Darstellung von signed Zahlen ab, aber in den meisten Implementierungen wird -1 herauskommen.
Beispiel:
int x = (int)(unsigned)-1; // x == -1 auf den meisten Plattformen
Geschichte
Im String-Handler wurde eine Funktion zur Größenvergleich verwendet: Wenn die Länge des Strings negativ sein kann, gab das Programm einen Fehler aus. Die Länge war jedoch vom Typ size_t (unsigned), und der Vergleichscode
if(length < 0)ergab immer false, was zu einer Endlosschleife und Speicherüberlauf führte.
Geschichte
Beim Parsen des Protokolls enthielten die Netzwerkpakete Felder als unsigned, während lokale Variablen signed waren. Aufgrund des Überlaufs von unsigned bei der Verarbeitung bestimmter Werte kam es zu falschen Berechnungen der Paketlänge, was zu einer Bufferoverflow-Sicherheitsanfälligkeit führte.
Geschichte
Das Datumsvergleichsmodul in den Logs speicherte das Datum als unsigned int, suchte jedoch den Datumsbereich in int. Einige Grenzwerte führten, anstatt die erwartete Ausnahme auszulösen, zu fehlerhaften Filtern von Einträgen und dem Verlust wichtiger Logs.