In C, la conversione automatica dei tipi avviene secondo il principio delle "usual arithmetic conversions". Quando sono coinvolti in un'espressione numeri dichiarati con segno diverso (signed/unsigned), si applicano le seguenti regole:
Esempio di aritmetica pericolosa:
int a = -1; // signed unsigned int b = 1; printf("%d\n", a < b); // sempre false, poiché a viene convertito in un unsigned molto grande
Il risultato: -1, convertito in unsigned, diventa un numero positivo molto grande.
Cosa ricordare:
Domanda: Che risultato restituirà l'espressione (int)(unsigned)-1?
Risposta errata attesa: "-1, perché -1 e stiamo convertendo in int."
Risposta corretta:
Nell'espressione (unsigned)-1 avviene prima la conversione di -1 in unsigned (su una piattaforma a 32 bit questo è 0xFFFFFFFF), poi di nuovo in signed int, che dipende anche dall'implementazione, ma spesso si ottiene di nuovo -1 (se si usa il two's complement). Tuttavia, è più corretto dire: Il risultato dipende dagli standard di rappresentazione dei numeri signed, ma nella maggior parte delle implementazioni risulterà -1.
Esempio:
int x = (int)(unsigned)-1; // x == -1 su la maggior parte delle piattaforme
Storia
Nell'handler delle stringhe è stata utilizzata una funzione di confronto delle lunghezze: se la lunghezza della stringa poteva essere negativa, il programma segnalava un errore. Tuttavia, la lunghezza era di tipo size_t (unsigned) e il confronto con
if(length < 0)restituiva sempre false, causando un ciclo infinito e overflow della memoria.
Storia
Durante il parsing del protocollo, i pacchetti di rete contenevano campi come unsigned, mentre le variabili locali erano signed. A causa del sovraccarico dell'unsigned durante l'elaborazione di alcuni valori, si sono verificati errori nei calcoli della lunghezza del pacchetto, portando a vulnerabilità di overflow del buffer.
Storia
Il modulo di confronto delle date nei log memorizzava la data come unsigned int, mentre cercava un intervallo di date in int. Alcuni valori limite, invece della risposta attesa di eccezione, portavano a una filtrazione errata delle registrazioni e alla perdita di log importanti.