addTo/subtractFrom accumulation bypasses declared column type bounds (Int 32-bit, Long ±2^53) at commit-merge

Open Beginner friendly
#1,372 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
Half a day
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
node.js, typescript
Domain
database

Research direction

Start with resources/tracked.ts around lines 590 and 82–97, then run the two named integration tests for qa110-atomic-edges and qa112-int-bound under both storage engines. Done means accumulated addTo/subtractFrom values respect Int and Long bounds, while the existing SQL arithmetic behavior remains unchanged.

Written by the indexing model from the issue text.

Description

area:storage

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

Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
1d 15h
Merged PRs (30d)
196

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from HarperFast/harper

All issues in HarperFast/harper

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.