HarperFast / HarperFast/harper
addTo/subtractFrom accumulation bypasses declared column type bounds (Int 32-bit, Long ±2^53) at commit-merge
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
## Summary
Incremental `addTo`/`subtractFrom` operations silently commit values that exceed a column's declared type bound. A single large delta that itself exceeds the bound IS correctly rejected — but the accumulated running total escapes validation entirely.
**Confirmed affected types (both engines, no divergence):**
- `Int` (32-bit): `addTo(1)` on a column holding `2^31−1` → commits `2147483648` with no error, no wrap
- `Int` underflow: `subtractFrom(1)` on `−2^31+1` → commits `−2147483649`
- `Long` (±2^53): two `addTo(2^53)` calls → commits `2^54 = 18014398509481984`
**Correct (unaffected):** SQL `UPDATE col = col + 1` correctly rejects the out-of-range resolved value (calls `set()` with the final computed value).
## Root cause
`Addition.update(prev) { return (+prev||0) + this.value }` at `resources/tracked.ts:590` returns the summed result directly to the storage layer **without routing through `set()`**. The per-delta validator in `set()` (≈82–97) validates `value.__op__ ? value.value : value` — i.e. the delta — which passes for any single in-range increment. The commit-merge path is unguarded.
## Impact
Any fleet using a typed `Int` column to cap a counter or quota (e.g. 32-bit sequence, rate-limit counter) or relying on the `Long` ±2^53 bound under `addTo`/`subtractFrom` workloads does not get that cap. Values silently exceed the declared range with no error and no data corruption (values stay exact JS-safe integers). The only safe workaround today is using SQL arithmetic UPDATE (which enforces correctly) or an open/untyped column.
## Fix
Re-validate the resolved sum against the column's type bound in `tracked.ts:590` — call the column validator with the committed result after merge, or inline the bound check.
## Repro
```
# Int overflow (F-018)
npm run test:integration -- "integrationTests/qa-scratch/qa110-atomic-edges.test.ts" # probe 6a
HARPER_STORAGE_ENGINE=lmdb npm run test:integration -- "integrationTests/qa-scratch/qa110-atomic-edges.test.ts"
# Int underflow + Long accumulation
npm run test:integration -- "integrationTests/qa-scratch/qa112-int-bound.test.ts"
HARPER_STORAGE_ENGINE=lmdb npm run test:integration -- "integrationTests/qa-scratch/qa112-int-bound.test.ts"
```
Harper commit: `7aaa5a152` (branch `kris/repl-no-revalidate-1302-core`; root cause in `tracked.ts` is branch-independent).
*Found by the automated QA explorer campaign (waves 33–34). 🤖 Generated with [Claude Code](https://claude.com/claude-code)*
Contributor guide
Assessment
This issue has not been assessed yet.