# Undefined Behavior

### **📋 Índice**

1. Fundamentos do Undefined Behavior
2. Categorias de Undefined Behavior
3. Exemplos Clássicos
4. Otimizações do Compilador e UB
5. Exploração de Segurança
6. Ferramentas de Detecção
7. Impacto e Consequências
8. Prevenção e Boas Práticas
9. Checklists de Segurança

***

### 🔍 **Fundamentos do Undefined Behavior**

#### **O que é Undefined Behavior?**

**Undefined Behavior (UB)** é o comportamento de uma construção de linguagem para a qual o padrão da linguagem não impõe qualquer requisito. Quando UB ocorre, o programa pode fazer qualquer coisa: desde funcionar como esperado até crashar, corromper dados ou executar código arbitrário.

#### **Princípio de Funcionamento**

```mermaid
graph TD
    A[Código com UB] --> B{Compilador}
    B --> C[Otimização agressiva]
    B --> D[Comportamento indefinido]
    
    C --> E[Código eliminado]
    C --> F[Suposições inválidas]
    
    D --> G[Resultados imprevisíveis]
    E --> G
    F --> G
    
    G --> H[Corrupção de memória]
    G --> I[Crashes]
    G --> J[Falhas de segurança]
    
    style B fill:#ffcc99
    style G fill:#ff9999
    style J fill:#ff3333
```

#### **Comparação com Comportamento Definido**

| Tipo                       | Descrição                                              | Exemplo            | Consequência               |
| -------------------------- | ------------------------------------------------------ | ------------------ | -------------------------- |
| **Implementation-Defined** | Comportamento documentado, mas varia por implementação | Tamanho de `int`   | Previsível, documentado    |
| **Unspecified Behavior**   | Várias possibilidades, implementação escolhe           | Ordem de avaliação | Imprevisível, mas seguro   |
| **Undefined Behavior**     | Comportamento completamente indefinido                 | Overflow signed    | Pode causar qualquer coisa |

#### **Exemplo Clássico**

```c
// undefined_behavior_example.c - Exemplos de UB

#include <stdio.h>
#include <limits.h>

int main() {
    // 1. Overflow de signed (UB!)
    int i = INT_MAX;
    i = i + 1;  // 🔴 Comportamento indefinido!
    printf("INT_MAX + 1 = %d\n", i);  // Pode imprimir qualquer coisa
    
    // 2. Divisão por zero (UB!)
    int a = 1, b = 0;
    int c = a / b;  // 🔴 UB - pode crashar
    
    // 3. Acesso fora dos limites (UB!)
    int arr[10];
    arr[10] = 42;  // 🔴 UB - pode corromper memória
    
    // 4. Uso após free (UB!)
    char *ptr = malloc(100);
    free(ptr);
    strcpy(ptr, "data");  // 🔴 UB - Use-After-Free
    
    // 5. Dereference de ponteiro nulo (UB!)
    int *null_ptr = NULL;
    *null_ptr = 42;  // 🔴 UB - geralmente crash
    
    // 6. Shift por valor negativo (UB!)
    int x = 1 << -1;  // 🔴 UB
    
    // 7. Shift maior que largura do tipo (UB!)
    int y = 1 << 33;  // 🔴 UB em sistemas 32-bit
    
    return 0;
}
```

***

### 📚 **Categorias de Undefined Behavior**

#### **Classificação de UB**

```python
#!/usr/bin/env python3
# ub_categories.py - Categorias de Undefined Behavior

class UBCategories:
    """Análise das categorias de Undefined Behavior"""
    
    @staticmethod
    def memory_errors():
        """Erros de memória"""
        print("💾 Erros de Memória")
        print("=" * 60)
        
        errors = {
            "Buffer Overflow": "Acesso além dos limites do array",
            "Use-After-Free": "Uso de memória após liberação",
            "Double Free": "Liberar mesma memória duas vezes",
            "Memory Leak": "Não liberar memória alocada",
            "Dangling Pointer": "Ponteiro para memória liberada",
            "Null Dereference": "Dereferenciar ponteiro nulo"
        }
        
        for error, desc in errors.items():
            print(f"   • {error}: {desc}")
    
    @staticmethod
    def arithmetic_errors():
        """Erros aritméticos"""
        print("\n🔢 Erros Aritméticos")
        print("=" * 60)
        
        errors = {
            "Signed Overflow": "Overflow em inteiro signed (UB!)",
            "Division by Zero": "Divisão por zero",
            "Invalid Shift": "Shift por valor negativo ou >= largura",
            "Conversion Overflow": "Overflow em conversão de tipos",
            "Negation Overflow": "Negação de INT_MIN"
        }
        
        for error, desc in errors.items():
            print(f"   • {error}: {desc}")
    
    @staticmethod
    def pointer_errors():
        """Erros de ponteiro"""
        print("\n🔍 Erros de Ponteiro")
        print("=" * 60)
        
        errors = {
            "Invalid Pointer Arithmetic": "Aritmética além dos limites do objeto",
            "Comparison of Unrelated Pointers": "Comparação de ponteiros não relacionados",
            "Pointer to Freed Memory": "Ponteiro para memória liberada",
            "Misaligned Access": "Acesso a endereço não alinhado",
            "Restrict Violation": "Violação de qualificadores restrict"
        }
        
        for error, desc in errors.items():
            print(f"   • {error}: {desc}")
    
    @staticmethod
    def sequence_point_errors():
        """Erros de sequence point"""
        print("\n⏱️ Sequence Point Errors")
        print("=" * 60)
        
        errors = {
            "Multiple Modification": "Modificar mesma variável múltiplas vezes",
            "Read-Modify-Write": "Ler e modificar sem sequence point",
            "Function Argument Order": "Ordem de avaliação de argumentos",
            "Assignment in Assert": "Atribuição dentro de assert"
        }
        
        for error, desc in errors.items():
            print(f"   • {error}: {desc}")
            print(f"      Exemplo: i = i++ + ++i;  // UB!")

# Executar
UBCategories.memory_errors()
UBCategories.arithmetic_errors()
UBCategories.pointer_errors()
UBCategories.sequence_point_errors()
```

#### **Tabela de UB por Operação**

```c
// ub_table.c - Tabela de operações com UB

#include <stdio.h>
#include <limits.h>

void demonstrate_ub() {
    // Operações aritméticas
    int a = INT_MAX; a++;           // Signed overflow
    int b = 1; b <<= 31;            // Shift overflow (32-bit)
    int c = 1 / 0;                  // Division by zero
    int d = -INT_MIN;               // Negation overflow
    
    // Operações com ponteiros
    int arr[10];
    int *p = arr + 11;              // Pointer beyond array
    *p = 42;                        // Dereference invalid pointer
    free(p);                        // Free invalid pointer
    
    // Operações com variáveis
    int i = 0;
    i = i++ + ++i;                  // Multiple modifications
    
    // Operações com tipos
    float f = 1e100;                // Floating overflow
    int x = (int)f;                 // Conversion overflow
}
```

***

### ⚡ **Exemplos Clássicos**

#### **1. Integer Overflow**

```c
// integer_overflow_ub.c - Overflow de inteiros

#include <stdio.h>
#include <limits.h>

// 🔴 Função vulnerável a UB por overflow
int vulnerable_multiply(int a, int b) {
    // O compilador pode assumir que a*b nunca overflowa!
    return a * b;
}

// ✅ Função segura com verificação
int safe_multiply(int a, int b) {
    if (a > 0 && b > 0 && a > INT_MAX / b) {
        return -1;  // Overflow detectado
    }
    if (a < 0 && b < 0 && a < INT_MAX / b) {
        return -1;
    }
    if (a > 0 && b < 0 && b < INT_MIN / a) {
        return -1;
    }
    return a * b;
}

// Demonstração de como UB afeta otimizações
int test_overflow(int x) {
    if (x + 1 > x) {  // 🔴 Compilador pode assumir sempre verdadeiro!
        return x * 2;
    }
    return 0;
}

int main() {
    int x = INT_MAX;
    printf("vulnerable_multiply: %d\n", vulnerable_multiply(x, 2));
    printf("test_overflow: %d\n", test_overflow(x));
    return 0;
}
```

#### **2. Sequence Points**

```c
// sequence_point_ub.c - Problemas de sequence point

#include <stdio.h>

// 🔴 Comportamento indefinido
void ub_sequence_points() {
    int i = 0;
    
    i = i++;           // UB: modificação múltipla
    i = ++i + i++;     // UB: múltiplas modificações
    i = i++ + ++i;     // UB: clássico
    
    printf("%d %d\n", i++, i++);  // UB: ordem de avaliação
    
    int arr[] = {1, 2, 3};
    int j = 0;
    arr[j] = j++;      // UB: leitura e modificação
}

// ✅ Comportamento definido
void defined_sequence_points() {
    int i = 0;
    
    i++;               // OK
    i = i + 1;         // OK
    ++i;               // OK
    
    int j = 0;
    arr[j] = 1;        // OK
    j++;               // OK
}

// Exemplo real de bug
int buggy_function(int *arr, int idx) {
    return arr[idx] = idx++;  // 🔴 UB - comportamento indefinido!
}

int fixed_function(int *arr, int idx) {
    arr[idx] = idx;    // OK
    idx++;
    return arr[idx-1];
}
```

#### **3. Strict Aliasing**

```c
// strict_aliasing_ub.c - Violação de strict aliasing

#include <stdio.h>
#include <stdint.h>

// 🔴 Violação de strict aliasing
void ub_strict_aliasing() {
    float f = 1.0f;
    int *ip = (int *)&f;  // 🔴 UB: ponteiro de tipo diferente
    *ip = 0x3F800000;     // Comportamento indefinido
    printf("f = %f\n", f);
}

// ✅ Usar union para type punning (em C)
union float_int {
    float f;
    int i;
};

void defined_type_punning() {
    union float_int u;
    u.f = 1.0f;
    u.i = 0x3F800000;  // OK em C
    printf("f = %f\n", u.f);
}

// ✅ Usar memcpy (recomendado)
void defined_memcpy() {
    float f;
    int i = 0x3F800000;
    memcpy(&f, &i, sizeof(f));
    printf("f = %f\n", f);
}

// Exemplo de otimização quebrada por aliasing
void process_buffers(int *int_buf, float *float_buf, int size) {
    for (int i = 0; i < size; i++) {
        int_buf[i] = (int)float_buf[i];  // Se int_buf e float_buf se sobrepõem, UB!
    }
}
```

***

### ⚡ **Otimizações do Compilador e UB**

#### **Como UB Afeta Otimizações**

```c
// compiler_optimizations_ub.c - Otimizações baseadas em UB

#include <stdio.h>

// 1. Eliminação de código baseada em UB
int ub_elimination(int x) {
    // Compilador assume que x não é NULL (porque dereferenciar NULL é UB)
    int y = *x;  // Se x for NULL, UB
    
    // Esta comparação pode ser eliminada!
    if (x == NULL) {
        return 0;  // 🔴 Compilador pode eliminar este branch
    }
    return y;
}

// O código otimizado pode ser equivalente a:
int ub_elimination_optimized(int x) {
    int y = *x;
    return y;  // Branch removido!
}

// 2. Assunções sobre overflow
int ub_overflow_assumption(int x) {
    // Compilador assume que x + 1 nunca overflowa (signed overflow é UB)
    // Portanto, x + 1 > x é SEMPRE verdadeiro
    if (x + 1 > x) {
        return x * 2;
    }
    return 0;  // 🔴 Este branch pode ser eliminado!
}

// 3. Loop invariants
int ub_loop_invariant(int *ptr, int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        // Compilador pode mover *ptr para fora do loop
        // Assumindo que ptr não muda e não é NULL
        sum += *ptr + i;
    }
    return sum;
}

// 4. Propagação de valor baseada em UB
int ub_value_propagation(int x) {
    int y = x;
    // Compilador assume que shift por 31 em 32-bit não overflow
    // (pois shift >= largura é UB)
    int z = y << 31;
    return z;
}

// Demonstração
int main() {
    int x = INT_MAX;
    printf("ub_overflow_assumption: %d\n", ub_overflow_assumption(x));
    return 0;
}
```

#### **Verificação de Otimizações**

```bash
#!/bin/bash
# check_optimizations.sh - Verificar otimizações baseadas em UB

# 1. Compilar com diferentes níveis
echo "[*] Compilando com -O0"
gcc -O0 -S -o with_ub_O0.s ub_example.c

echo "\n[*] Compilando com -O2"
gcc -O2 -S -o with_ub_O2.s ub_example.c

# 2. Comparar assembly
echo "\n[*] Diferenças no assembly"
diff with_ub_O0.s with_ub_O2.s

# 3. Compilar com flags de UB
echo "\n[*] Compilando com flags de detecção"
gcc -fsanitize=undefined -g -o ub_test ub_example.c

# 4. Executar com UBSAN
echo "\n[*] Executando com UBSAN"
./ub_test 2>&1 | grep "runtime error"

# 5. Verificar otimizações perigosas
echo "\n[*] Flags que podem causar problemas"
gcc -O2 -fstrict-aliasing -Wstrict-aliasing=2 -o test test.c
```

***

### 🔓 **Exploração de Segurança**

#### **UB como Vetor de Ataque**

```c
// ub_exploitation.c - Exploração de UB para segurança

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 1. Overflow de buffer (UB) levando a RCE
void vulnerable_function(char *input) {
    char buffer[64];
    // 🔴 UB quando input > 64
    strcpy(buffer, input);  // Buffer overflow
    printf("Buffer: %s\n", buffer);
}

// 2. Signed overflow em verificações
int check_auth(int user_id, int level) {
    int required_level = 5;
    // 🔴 Se user_id + level overflow, pode bypassar verificação
    if (user_id + level > required_level) {
        return 1;  // Autorizado
    }
    return 0;
}

// Exemplo: user_id = INT_MAX, level = 1
// INT_MAX + 1 = INT_MIN (underflow) -> bypass!

// 3. Shift overflow em alocações
void* allocate_buffer(size_t size) {
    // 🔴 Se size * sizeof(int) overflow, malloc aloca menos
    int *buffer = malloc(size * sizeof(int));
    if (!buffer) return NULL;
    
    // 🔴 Se overflow, podemos escrever além do buffer
    for (size_t i = 0; i < size; i++) {
        buffer[i] = i;
    }
    return buffer;
}

// 4. Null pointer dereference em kernel
// Em kernel, dereferenciar ponteiro nulo pode levar a privilégios
struct user_data {
    char name[64];
    int uid;
};

int kernel_function(struct user_data __user *user_ptr) {
    struct user_data *kernel_ptr = user_ptr;
    // 🔴 Se user_ptr == NULL, kernel crash ou pode ser explorado
    return kernel_ptr->uid;
}
```

#### **UB em JIT Engines**

```c
// jit_ub_exploit.c - Exploração de UB em JIT

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Simulação de JIT engine vulnerável
typedef struct {
    unsigned char *code;
    size_t size;
} jit_buffer;

jit_buffer* jit_compile(char *source) {
    jit_buffer *buf = malloc(sizeof(jit_buffer));
    
    // Simular compilação
    buf->size = strlen(source) * 4;  // 🔴 Possível overflow
    buf->code = malloc(buf->size);
    
    // Gerar código (simplificado)
    unsigned char prologue[] = {
        0x55,                   // push rbp
        0x48, 0x89, 0xE5,      // mov rbp, rsp
    };
    
    memcpy(buf->code, prologue, sizeof(prologue));
    
    // 🔴 Se source for malicioso, pode injetar código
    // (omitting bounds check)
    
    unsigned char epilogue[] = {
        0x5D,                   // pop rbp
        0xC3                    // ret
    };
    memcpy(buf->code + buf->size - sizeof(epilogue), epilogue, sizeof(epilogue));
    
    return buf;
}

int main() {
    // Payload malicioso que explora UB
    char malicious[] = 
        "\x48\x31\xC0"          // xor rax, rax
        "\x48\x83\xC0\x3B"      // add rax, 0x3B (execve)
        "\x48\x31\xFF"          // xor rdi, rdi
        "\x48\xBF\x2F\x62\x69\x6E\x2F\x73\x68\x00"  // mov rdi, "/bin/sh"
        "\x48\x31\xF6"          // xor rsi, rsi
        "\x48\x31\xD2"          // xor rdx, rdx
        "\x0F\x05";             // syscall
    
    jit_buffer *buf = jit_compile(malicious);
    
    // Executar código JIT (pode conter shellcode)
    void (*func)(void) = (void (*)(void))buf->code;
    func();
    
    return 0;
}
```

***

### 🛠️ **Ferramentas de Detecção**

#### **Sanitizers do Compilador**

```bash
#!/bin/bash
# sanitizers_demo.sh - Demonstração de sanitizers

# 1. AddressSanitizer (ASAN)
echo "[*] AddressSanitizer"
gcc -fsanitize=address -g -o test_asan test.c
./test_asan

# 2. UndefinedBehaviorSanitizer (UBSAN)
echo "\n[*] UndefinedBehaviorSanitizer"
gcc -fsanitize=undefined -g -o test_ubsan test.c
./test_ubsan

# 3. LeakSanitizer (LSAN)
echo "\n[*] LeakSanitizer"
gcc -fsanitize=leak -g -o test_lsan test.c
./test_lsan

# 4. MemorySanitizer (MSAN)
echo "\n[*] MemorySanitizer"
gcc -fsanitize=memory -g -o test_msan test.c
./test_msan

# 5. ThreadSanitizer (TSAN)
echo "\n[*] ThreadSanitizer"
gcc -fsanitize=thread -g -o test_tsan test.c
./test_tsan

# 6. Combinar sanitizers
echo "\n[*] Múltiplos sanitizers"
gcc -fsanitize=address,undefined,leak -g -o test_all test.c
./test_all
```

#### **Detecção Estática**

```python
#!/usr/bin/env python3
# ub_static_detection.py - Detecção estática de UB

import re
import sys

class UBStaticDetector:
    """Detector estático de Undefined Behavior"""
    
    @staticmethod
    def detect_signed_overflow(code):
        """Detectar padrões de overflow signed"""
        print("[*] Detectando overflow signed")
        
        patterns = [
            r'int\s+\w+\s*=\s*INT_MAX\s*[+*]',
            r'INT_MAX\s*[+*]',
            r'\w+\s*=\s*\w+\s*\+\s*INT_MAX',
            r'INT_MAX\s*\+\s*1'
        ]
        
        for pattern in patterns:
            matches = re.findall(pattern, code)
            if matches:
                print(f"   ⚠️ Possível signed overflow: {matches}")
    
    @staticmethod
    def detect_shift_overflow(code):
        """Detectar shift overflow"""
        print("\n[*] Detectando shift overflow")
        
        patterns = [
            r'<<\s*[0-9]{2,}',  # Shift por >31
            r'>>\s*[0-9]{2,}',
            r'<<\s*-',
            r'>>\s*-'
        ]
        
        for pattern in patterns:
            matches = re.findall(pattern, code)
            if matches:
                print(f"   ⚠️ Possível shift overflow: {matches}")
    
    @staticmethod
    def detect_sequence_point(code):
        """Detectar problemas de sequence point"""
        print("\n[*] Detectando problemas de sequence point")
        
        patterns = [
            r'\w+\s*=\s*\w+\+\+\s*\+\s*\+\+\w+',  # i = i++ + ++i
            r'\w+\s*=\s*\w+\+\+',                 # i = i++
            r'printf\s*\(.*\w\+\+\s*,\s*\w\+\+',  # printf(i++, i++)
            r'arr\[i\]\s*=\s*i\+\+',              # arr[i] = i++
            r'arr\[i\+\+\]\s*=\s*i'               # arr[i++] = i
        ]
        
        for pattern in patterns:
            matches = re.findall(pattern, code)
            if matches:
                print(f"   ⚠️ Possível sequence point violation: {matches}")
    
    @staticmethod
    def detect_null_dereference(code):
        """Detectar dereferência de ponteiro nulo"""
        print("\n[*] Detectando dereferência de ponteiro nulo")
        
        patterns = [
            r'NULL\s*->',
            r'\*\s*NULL',
            r'if\s*\(\s*\w+\s*==\s*NULL\s*\)\s*\w+\s*->'
        ]
        
        for pattern in patterns:
            matches = re.findall(pattern, code)
            if matches:
                print(f"   ⚠️ Possível null dereference: {matches}")

# Uso
if __name__ == "__main__":
    if len(sys.argv) > 1:
        with open(sys.argv[1], 'r') as f:
            code = f.read()
        
        UBStaticDetector.detect_signed_overflow(code)
        UBStaticDetector.detect_shift_overflow(code)
        UBStaticDetector.detect_sequence_point(code)
        UBStaticDetector.detect_null_dereference(code)
    else:
        print("Uso: ub_static_detection.py <source.c>")
```

***

### 🛡️ **Prevenção e Boas Práticas**

#### **Técnicas de Prevenção**

```c
// ub_prevention.c - Técnicas para evitar UB

#include <stdio.h>
#include <limits.h>
#include <stdint.h>

// 1. Verificação de overflow em multiplicação
int safe_multiply(int a, int b) {
    if (a > 0 && b > 0 && a > INT_MAX / b) return -1;
    if (a < 0 && b < 0 && a < INT_MAX / b) return -1;
    if (a > 0 && b < 0 && b < INT_MIN / a) return -1;
    if (a < 0 && b > 0 && a < INT_MIN / b) return -1;
    return a * b;
}

// 2. Verificação de overflow em adição
int safe_add(int a, int b) {
    if ((b > 0 && a > INT_MAX - b) ||
        (b < 0 && a < INT_MIN - b)) {
        return -1;  // Overflow
    }
    return a + b;
}

// 3. Uso de tipos unsigned para aritmética modular
unsigned int modular_add(unsigned int a, unsigned int b) {
    return a + b;  // OK: wrap-around definido
}

// 4. Verificação de shift
int safe_shift_left(int value, int shift) {
    if (shift < 0 || shift >= sizeof(int) * 8) {
        return -1;  // Shift inválido
    }
    return value << shift;
}

// 5. Uso de __builtin_* para detecção
int builtin_safe_add(int a, int b) {
    int result;
    if (__builtin_add_overflow(a, b, &result)) {
        return -1;  // Overflow detectado
    }
    return result;
}

// 6. Inicialização de ponteiros
void safe_pointer_usage() {
    int *ptr = NULL;
    
    // Verificar antes de usar
    if (ptr != NULL) {
        *ptr = 42;
    }
}

// 7. Limites de array
void safe_array_access(int *arr, size_t size, size_t index) {
    if (index < size) {
        arr[index] = 42;
    }
}

// 8. Uso de qualificadores de tipo
void safe_type_punning() {
    float f;
    uint32_t i;
    
    // Usar memcpy em vez de cast
    memcpy(&i, &f, sizeof(i));
    memcpy(&f, &i, sizeof(f));
}

// 9. Compilação com flags defensivas
// gcc -fwrapv -fno-strict-aliasing -fno-strict-overflow -Werror
```

#### **Boas Práticas**

```yaml
Boas Práticas para Evitar UB:

  ✅ Compilação:
    - Usar `-Wall -Wextra -Werror`
    - Habilitar `-fsanitize=undefined` em debug
    - Usar `-fwrapv` para overflow definido
    - Desabilitar `-fstrict-aliasing` se necessário

  ✅ Verificações:
    - Sempre verificar limites de array
    - Verificar ponteiros antes de dereferenciar
    - Verificar overflow em operações aritméticas
    - Inicializar todas as variáveis

  ✅ Ferramentas:
    - Valgrind para detecção de UB
    - ASAN/UBSAN em testes
    - Análise estática (Clang, Coverity)
    - Fuzzing para encontrar UB

  ✅ Codificação:
    - Evitar casts perigosos
    - Usar tipos unsigned para aritmética modular
    - Documentar assumptions de segurança
    - Revisar código com UB em mente
```

***

### 📋 **Checklists de Segurança**

#### **Checklist para Desenvolvedores**

* [ ] Verificar overflow em operações aritméticas
* [ ] Validar limites de array antes do acesso
* [ ] Inicializar todas as variáveis
* [ ] Verificar ponteiros antes de usar
* [ ] Evitar casts de tipos incompatíveis
* [ ] Não assumir ordem de avaliação de argumentos
* [ ] Usar `__builtin_*_overflow` quando disponível
* [ ] Compilar com `-fsanitize=undefined` em testes

#### **Checklist para Revisão de Código**

* [ ] Buscar padrões de UB conhecidos
* [ ] Verificar loops com índices
* [ ] Analisar operações com signed integers
* [ ] Verificar shifts e operações de bits
* [ ] Analisar conversões de tipo
* [ ] Verificar sequence points
* [ ] Confirmar aliasing correto

***

### 📊 **Conclusão**

```yaml
Undefined Behavior:

  🔴 Principais Categorias:
    - Memory errors (buffer overflow, UAF)
    - Arithmetic errors (signed overflow, division by zero)
    - Pointer errors (null dereference, invalid arithmetic)
    - Sequence point violations
    - Strict aliasing violations

  🛡️ Mitigações Essenciais:
    - Sanitizers (ASAN, UBSAN)
    - Compiler flags (-Werror -fwrapv)
    - Static analysis
    - Code review focada em UB
    - Fuzzing

  🎯 Prioridade:
    - CRÍTICA: Memory errors
    - ALTA: Arithmetic errors em verificações
    - MÉDIA: Sequence point violations
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/tecnicas/linguagens-de-programacao/low-level/undefined-behavior.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
