# Error path frees uninitialized or stack pointer

Cleanup and error handlers calling free on pointers never initialized or pointing into the stack

_Area: Memory corruption and native code. Seen in 2 disclosed reports; one confirmed bounty: $1,500; latest 2024-08-23. Updated 2026-10-25._

## How it works
A cleanup or error handler assumes every pointer it frees was allocated on the heap and initialized. That assumption breaks in two ways: the pointer is a stack-local scratch buffer, or it is an uninitialized field in a struct whose allocation loop never ran. When the error branch is reached, `free()` is applied to memory that was never heap-allocated, corrupting allocator or stack state. The happy path is usually correct; only the invalid-input or overflow branch is wrong.

## Where it shows up
- A local array (e.g. a small fixed scratch buffer) passed to `free()` on an error return [E3](https://bugbountylibrary.com/r/h1%3A2621057.md).
- Cleanup loops that free struct members before the loop that allocates them has run, or that a counter decrement makes unreachable [E2](https://bugbountylibrary.com/r/h1%3A478367.md).
- Error paths after an integer-overflow or bounds check that jump straight to cleanup.
- Vendored libraries missing an upstream CVE patch, so the original bug and any patch-introduced bug both persist [E2](https://bugbountylibrary.com/r/h1%3A478367.md).
- Parsers of attacker-controlled input (certs, image headers, FastCGI vars) where invalid data triggers the error branch [E1](https://bugbountylibrary.com/r/h1%3A722327.md)[E3](https://bugbountylibrary.com/r/h1%3A2621057.md).

## How to review
For every `free()`/`efree()` in a cleanup or error handler, trace back: is this pointer guaranteed heap-allocated and initialized on every path that reaches the free? Check that allocation loops run before cleanup loops, that counters cannot go negative and skip initialization, and that stack buffers are never passed to free. The invariant: a pointer is freed only if it was heap-allocated and assigned on the current path. Also diff vendored code against upstream fixes [E2](https://bugbountylibrary.com/r/h1%3A478367.md).

## Variants seen
- Free of a 4-byte stack buffer on invalid UTF-8 in ASN1 parsing [E3](https://bugbountylibrary.com/r/h1%3A2621057.md).
- Free of uninitialized struct-member pointers when an overflow check fails and a `u--` skips the init loop [E2](https://bugbountylibrary.com/r/h1%3A478367.md).
- Pointer underflow from a missing bounds check on an empty variable, giving a one-byte OOB write [E1](https://bugbountylibrary.com/r/h1%3A722327.md).

## Impact and severity
Led to use-after-free and potential RCE [E2](https://bugbountylibrary.com/r/h1%3A478367.md), stack corruption from a malicious TLS server [E3](https://bugbountylibrary.com/r/h1%3A2621057.md), and OOB write escalating to RCE [E1](https://bugbountylibrary.com/r/h1%3A722327.md). Severity rises when the error path is reachable from remote, unauthenticated input and when a front-end proxy can be tricked into producing the triggering value [E1](https://bugbountylibrary.com/r/h1%3A722327.md).

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A722327.md
- E2: https://bugbountylibrary.com/r/h1%3A478367.md
- E3: https://bugbountylibrary.com/r/h1%3A2621057.md
