# Memory pointer can overflow in hintstore

Hintstore's per-limb byte range check let a full 32-bit address overflow BabyBear's modulus, allowing writes to attacker-selected memory addresses.

- Payout: Contest reward
- Severity: medium
- Program: OpenVM
- Credited: Leo Alt
- Disclosed: 2025-03-24
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_openvm_january2025.pdf#3.2.2
- Library page: https://bugbountylibrary.com/r/cantina%3Aopenvm_january2025%3A3.2.2
- Tags: domain:web3 impact:integrity kind:contest platform:cantina sev:medium tech:rust technique:source-review vuln:business-logic vuln:memory-corruption

**Target:** hintstore memory pointer handling in mod.rs
**Root cause:** Hintstore range-checked each limb to a byte but did not constrain the most significant limb, so a 32-bit value could exceed BabyBear's modulus p and wrap the computed memory pointer.
**Steps:**
1. Compute p = (1<<31) - (1<<27) + 1 (BabyBear modulus).
2. Take address of a stack variable n_ptr and add p as usize to form overflow_addr.
3. Cast to *mut u32 and call `hint_buffer_u32!(overflow_ptr, 1)` to write via the overflowing pointer.
4. Observe n changed, proving write to a selected address.
**How found:** Noticed the range check only validated each limb to a byte, then reasoned a full 32-bit number could still overflow BabyBear's modulus p; crafted a PoC calling hint_buffer_u32 directly with an overflowing address.
**Exploitation:** Attacker calls the hint function directly with an address that overflows p, causing the pointer arithmetic to wrap and write to a chosen memory location, overwriting the target variable.
**Insight:** When a field element is built limb-by-limb, check that the top limb is constrained to the remaining bit budget (here 5 bits for a 29-bit address); otherwise the assembled value can exceed the modulus and wrap pointer arithmetic.
