# Immediate value used as pointer

Interpreter or wrapper passes an integer/immediate where a heap object pointer is expected, then dereferences it

_Area: Memory corruption and native code. Seen in 3 disclosed reports; 3 confirmed bounties, median $1,000, range $500-$1,000; latest 2019-10-31. Updated 2026-11-02._

## How it works
A value that is not a pointer gets used as one. Interpreters and wrappers often carry two kinds of value in the same slot: real heap-object pointers, and immediates (small integers, symbols, nil, mode constants). A code path skips the check that tells them apart and hands the raw immediate to a routine that dereferences it. The assumption that breaks is "this receiver/argument is a heap object" — it holds for normal calls but not for attacker-chosen values. The dereference then reads or writes an address the attacker influenced, giving a crash and sometimes control [E1](https://bugbountylibrary.com/r/h1%3A161200.md)[E2](https://bugbountylibrary.com/r/h1%3A621308.md)[E3](https://bugbountylibrary.com/r/h1%3A167688.md).

## Where it shows up
- Instance-variable methods (`remove_instance_variable`, `instance_variable_get/set`) that act on the receiver without confirming it is a heap object [E2](https://bugbountylibrary.com/r/h1%3A621308.md).
- Deserializer branches that turn a string field into a numeric or pointer value; embedded control characters like `\r` can desync the parser so field bytes become an address [E1](https://bugbountylibrary.com/r/h1%3A161200.md).
- Language wrappers forwarding an integer to a native API whose parameter is overloaded: small values are mode constants, large values are dereferenced as string pointers [E3](https://bugbountylibrary.com/r/h1%3A167688.md).
- Any FFI/binding that passes a Python/Ruby int straight into a C `void*` or `char*` parameter.

## How to review
Find every place an immediate can reach a pointer-typed parameter or a dereference. The invariant: before any dereference, the value must be proven to be a tagged heap object (tag check, type check, or whitelist of allowed constants). For overloaded native parameters, check that the wrapper validates the argument against the known constant set and rejects everything else [E3](https://bugbountylibrary.com/r/h1%3A167688.md). For parsers, check that a field's bytes cannot flow into a pointer or length without full validation, and that control characters cannot split or shift fields [E1](https://bugbountylibrary.com/r/h1%3A161200.md).

## How finders spotted it
- Fuzzed the deserializer under ASAN, noticed the crash correlated with a `\r` inside a dateTime value, then used gdb to confirm the timestamp bytes landed in the register used for reading [E1](https://bugbountylibrary.com/r/h1%3A161200.md).
- Suspected methods assuming a heap-object receiver; valgrind flagged an invalid read at a poison address, and gdb confirmed the FIXNUM value was used as a pointer [E2](https://bugbountylibrary.com/r/h1%3A621308.md).
- Read the wrapper's pass-through of `persist` to the Win32 call, knew the API's overloaded semantics, and confirmed with a debugger crash dump [E3](https://bugbountylibrary.com/r/h1%3A167688.md).

## Variants seen
- Parser desync: control character in a string field makes the parser treat field bytes as an address [E1](https://bugbountylibrary.com/r/h1%3A161200.md).
- Missing receiver type check: immediate (FIXNUM) passed as `void*` to a freeze check [E2](https://bugbountylibrary.com/r/h1%3A621308.md).
- Overloaded native parameter: integer forwarded where the API expects either a constant or a string pointer [E3](https://bugbountylibrary.com/r/h1%3A167688.md).

## Impact and severity
All three produced illegal memory access or crashes; bounties were modest (median 1000). E3's impact is raised by a theorized chain: memory spray plus a controlled pointer could yield attacker-controlled file creation and RCE [E3](https://bugbountylibrary.com/r/h1%3A167688.md). E1 and E2 showed no escalation in the evidence.

## Seen in real software
Open-source packages and projects, and products, where this pattern was found. If the target runs one, compare the version it runs with the fix.
- **PHP**: wddx_deserialize allows illegal memory access. Report: https://bugbountylibrary.com/r/h1%3A161200.md
- **CPython**: msilib.OpenDatabase Type Confusion. Report: https://bugbountylibrary.com/r/h1%3A167688.md

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A161200.md
- E2: https://bugbountylibrary.com/r/h1%3A621308.md
- E3: https://bugbountylibrary.com/r/h1%3A167688.md
