In C werkt automatische typeconversie volgens het principe van 'usual arithmetic conversions'. Wanneer getallen met verschillende tekens (signed/unsigned) bij een expressie betrokken zijn, worden de volgende regels toegepast:
Voorbeeld van gevaarlijke rekenkunde:
int a = -1; // signed unsigned int b = 1; printf("%d\n", a < b); // altijd false, omdat a wordt omgezet naar een zeer groot unsigned
Resultaat: -1, wanneer omgezet naar unsigned, wordt een zeer groot positief getal.
Wat belangrijk is om te onthouden:
Vraag: Wat is het resultaat van de expressie (int)(unsigned)-1?
Verwacht onjuist antwoord: "-1, want -1 en we zetten het om naar int."
Juiste antwoord:
In de expressie (unsigned)-1 vindt eerst de conversie van -1 naar unsigned plaats (op een 32-bits platform is dit 0xFFFFFFFF), vervolgens weer terug naar signed int, wat ook afhankelijk is van de implementatie, maar vaak resulteert in -1 (als two's complement wordt gebruikt). Het is echter correcter te zeggen: Het resultaat hangt af van de standaarden voor de weergave van signed getallen, maar in de meeste implementaties zal het -1 zijn.
Voorbeeld:
int x = (int)(unsigned)-1; // x == -1 op de meeste platforms
Verhaal
In de stringverwerker werd een functie voor het vergelijken van lengtes gebruikt: als de lengte van de string negatief kon zijn, gaf het programma een foutmelding. Echter, de lengte was van het type size_t (unsigned), en de vergelijkingif(length < 0)gaf altijd false, wat leidde tot een oneindige lus en een geheugenoverloop.
Verhaal
Bij het parseren van het protocol bevatten netwerkkaves velden als unsigned, terwijl lokale variabelen signed waren. Door overloop van unsigned bij het verwerken van sommige waarden ontstonden er onjuiste berekeningen van de pakketlengte, wat resulteerde in een buffer-overloop kwetsbaarheid.
Verhaal
De module voor het vergelijken van datums in logs slaat de datum op als unsigned int, terwijl het een datumbereik in int zocht. Sommige grenswaarden gaven, in plaats van de verwachte uitzondering, onjuiste filtering van records en verlies van belangrijke logs.