Regola
Prevenire i pattern comuni di segmentation fault.
La dereferenziazione di puntatori nulli, i buffer overflow
e gli errori di use-after-free causano arresti anomali e vulnerabilità di sicurezza.
Linguaggi supportati: C/C++Introduzione
I segmentation fault rimangono la causa più comune di arresti anomali e vulnerabilità sfruttabili nelle applicazioni C/C++. Queste violazioni dell'accesso alla memoria si verificano quando il codice tenta di leggere o scrivere memoria che non possiede, tipicamente attraverso la dereferenziazione di puntatori nulli, buffer overflow, puntatori pendenti (dangling pointers) o l'accesso a memoria liberata. Un singolo segfault può mandare in tilt i server di produzione e, peggio ancora, molti pattern di segfault sono sfruttabili per l'esecuzione di codice arbitrario.
Perché è importante
Implicazioni sulla sicurezza: I buffer overflow e le vulnerabilità use-after-free sono alla base della maggior parte degli exploit di corruzione della memoria. Gli aggressori li sfruttano per sovrascrivere gli indirizzi di ritorno, iniettare shellcode o manipolare il flusso di controllo del programma. La vulnerabilità Heartbleed del 2014 era un buffer over-read. Gli exploit moderni prendono ancora di mira questi pattern perché offrono agli aggressori un accesso diretto alla memoria.
Stabilità del sistema: I segmentation fault mandano in crash l'applicazione immediatamente, senza alcuna degradazione graduale. Nei sistemi di produzione, ciò significa richieste perse, transazioni interrotte e stato corrotto. A differenza delle eccezioni nei linguaggi di livello superiore che possono essere intercettate, i segfault terminano il processo, richiedendo procedure di riavvio e ripristino.Ampliamento dellasuperficie di attacco: Qualsiasi dereferenziazione di puntatore non controllata, strcpy, memcpy, o accesso a un array senza controllo dei limiti, rappresenta un potenziale punto di ingresso per lo sfruttamento. Gli aggressori concatenano queste vulnerabilità, usandone una per corrompere la memoria in modi che consentono di sfruttarne un'altra.
Esempi di codice
❌ Non conforme:
void process_user_data(const char* input) {
char buffer[64];
strcpy(buffer, input); // No bounds checking
char* token = strtok(buffer, ",");
while (token != NULL) {
process_token(token);
token = strtok(NULL, ",");
}
}
int* get_config_value(int key) {
int* value = (int*)malloc(sizeof(int));
*value = lookup_config(key);
return value; // Caller must free, but no documentation
}Perché non è sicuro: Il parametro strcpy() la chiamata causa un buffer overflow se l'input supera i 63 byte, consentendo agli aggressori di sovrascrivere la memoria dello stack. La funzione get_config_value() perde memoria a ogni chiamata e crea il rischio di puntatori pendenti (dangling pointer) se i chiamanti liberano la memoria mentre altro codice vi fa ancora riferimento.
✅ Conforme:
void process_user_data(const char* input) {
if (!input) return;
size_t input_len = strlen(input);
char* buffer = malloc(input_len + 1);
if (!buffer) return;
strncpy(buffer, input, input_len);
buffer[input_len] = '\0';
char* token = strtok(buffer, ",");
while (token != NULL) {
process_token(token);
token = strtok(NULL, ",");
}
free(buffer);
}
int get_config_value(int key, int* out_value) {
if (!out_value) return -1;
*out_value = lookup_config(key);
return 0; // Caller owns out_value memory
}Perché è sicuro: I controlli sui puntatori nulli prevengono i crash da dereferenziazione. L'allocazione dinamica elimina i limiti fissi sulla dimensione del buffer. La copia con controllo dei limiti tramite strncpy() previene l'overflow. Chiare semantiche di proprietà in get_config_value() in cui il chiamante fornisce la memoria evitano confusione nell'allocazione e perdite (leak).
Conclusione
La sicurezza della memoria in C e C++ richiede una programmazione difensiva in ogni operazione sui puntatori e in ogni allocazione di memoria. I segmentation fault non sono inevitabili: possono essere prevenuti tramite controlli sui valori nulli coerenti, convalida dei limiti e chiari pattern di proprietà della memoria. Intercettare questi pattern prima della produzione previene sia i crash che le vulnerabilità sfruttabili.

