---
name: use-after-free-finder
description: Detects use-after-free and double-free bugs
---

**Finding ID Prefix:** `UAF` (e.g., UAF-001, UAF-002)

**Bug Patterns to Find:**

1. **Classic Use-After-Free**
   - Memory freed, then accessed through stale pointer
   - Multiple shared_ptr to same object with incorrect refcount

2. **Use After Scope (Dangling Pointers)**
   - Heap structures storing pointers to stack variables
   - Returning pointer to local variable
   - Capturing local by reference in escaping lambda

3. **Use After Return**
   - `return string("").c_str()` - buffer destroyed on return
   - Returning pointer to temporary object

4. **Use After Close**
   - File descriptor reused after close
   - Handle accessed after release

5. **Double Free**
   - Same pointer freed twice
   - Freeing in destructor and manually

6. **Arbitrary Pointer Free**
   - Freeing non-heap memory
   - Freeing uninitialized pointer

7. **Incorrect Refcounts**
   - Refcount incremented incorrectly
   - Object not freed when refcount hits zero

8. **Partial Free**
   - Struct field freed but struct not
   - Container freed but elements not

9. **Library Function Misuse**
   - OpenSSL BN_CTX_start without BN_CTX_end
   - Other allocator/deallocator mismatches

**Common False Positives to Avoid:**

- **Pointer reassigned before use:** If pointer is set to new allocation after free, not UAF
- **Pointer set to NULL after free:** Defensive coding; subsequent NULL check prevents use
- **Smart pointer managed lifetime:** `unique_ptr` and properly used `shared_ptr` handle lifetime
- **Pool allocators:** Object returned to pool, then same memory reused - intentional, not UAF
- **Realloc success path:** `ptr = realloc(ptr, size)` - old ptr invalid only if realloc succeeds
- **Static/global lifetime:** Pointers to static storage don't become dangling at scope exit
- **Reference counting verified:** If refcount is checked and correct, not a real UAF

**Search Patterns:**
```
free\s*\(|delete\s+|delete\s*\[
shared_ptr|unique_ptr|weak_ptr
->|\.get\(\)|\.release\(\)
return.*\.c_str\(\)|return.*\.data\(\)
close\s*\(|fclose\s*\(
```
