Regra
Prevenir comum segmentação falhas padrões.
Nulo ponteiro desreferências, buffer buffer,
e uso depois de livre erros causam crashes e segurança vulnerabilidades.
Linguagens suportadas: C/C++Introdução
Falhas de segmentação continuam sendo a fonte mais comum de travamentos e vulnerabilidades exploráveis em aplicações C/C++. Essas violações de acesso à memória ocorrem quando o código tenta ler ou escrever em memória que não lhe pertence, tipicamente através de desreferências de ponteiros nulos, estouros de buffer, ponteiros pendentes (dangling pointers) ou acesso a memória liberada. Um único segfault pode derrubar servidores de produção, mas pior, muitos padrões de segfault são exploráveis para execução arbitrária de código.
Por que isso importa
Implicações de segurança: Vulnerabilidades de estouro de buffer e use-after-free são a base da maioria dos exploits de corrupção de memória. Atacantes as utilizam para sobrescrever endereços de retorno, injetar shellcode ou manipular o fluxo de controle do programa. A vulnerabilidade Heartbleed de 2014 foi uma leitura excessiva de buffer. Exploits modernos ainda visam esses padrões porque fornecem acesso direto à memória aos atacantes.
Estabilidade do sistema: Falhas de segmentação travam sua aplicação imediatamente, sem degradação elegante. Em sistemas de produção, isso significa requisições perdidas, transações interrompidas e estado corrompido. Ao contrário das exceções de linguagens de alto nível que podem ser capturadas, os segfaults encerram o processo, exigindo procedimentos de reinício e recuperação.Expansão da superfície de ataque: Cada desreferência de ponteiro não verificada, strcpy, memcpy, ou acesso a arrays sem verificação de limites é um ponto de entrada potencial para exploração. Atacantes encadeiam essas vulnerabilidades, usando uma para corromper a memória de formas que permitem explorar outra.
Exemplos de código
❌ Não-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
}Por que é inseguro: O strcpy() chamada causa estouro de buffer se a entrada exceder 63 bytes, permitindo que atacantes sobrescrevam a memória da pilha. O get_config_value() A função vaza memória a cada chamada e cria risco de ponteiro pendente se os chamadores liberarem a memória enquanto outro código ainda a referencia.
✅ Compatível:
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
}Por que é seguro: Verificações de ponteiro nulo previnem falhas de desreferência. A alocação dinâmica elimina limites fixos de tamanho de buffer. Cópia com verificação de limites com strncpy() previne estouro de buffer. Semântica de propriedade clara em get_config_value() onde o chamador fornece memória para evitar confusão de alocação e vazamentos.
Conclusão
A segurança de memória em C e C++ exige programação defensiva em cada operação de ponteiro e alocação de memória. Falhas de segmentação não são inevitáveis, elas são evitáveis através de verificações de nulo consistentes, validação de limites e padrões claros de propriedade de memória. Identificar esses padrões antes da produção previne tanto falhas quanto vulnerabilidades exploráveis.
.avif)
