Skip to content

fix: F-7 VM type guards for unchecked accessor calls#33

Merged
b-macker merged 1 commit into
masterfrom
audit/f7-vm-type-guards
Jun 14, 2026
Merged

fix: F-7 VM type guards for unchecked accessor calls#33
b-macker merged 1 commit into
masterfrom
audit/f7-vm-type-guards

Conversation

@b-macker

Copy link
Copy Markdown
Owner

Summary

Closes the last deferred finding from R8 audit — F-7: unchecked .asInt()/.asString()/.asDictConst()/.asVMClosure() calls in vm.cpp.

Deep analysis reduced the original estimate of ~82 unsafe sites to 11 actual unguarded accessors (the rest were already guarded by inline type checks):

  • 8 constant-pool .asString() calls → new READ_CONSTANT_STRING macro with type + bounds checking
  • 1 .asInt() in OP_ITER_NEXTisInt() guard (crash on non-int index = stack corruption)
  • 1 .asDictConst() in OP_POLYGLOTisDict() guard (defense-in-depth)
  • 1 .asVMClosure() in OP_CLOSUREisVMClosure() guard (defense-in-depth)

Error messages use "Internal error" prefix (not "Type error") — these indicate VM/compiler bugs, not user code errors.

Changes

  • src/vm/vm.cpp: +37/-9 lines — READ_CONSTANT_STRING macro + 3 inline type guards

Test plan

  • Build: cmake .. && make naab-lang -j4 — 0 errors, 0 warnings
  • Full test suite: bash run-all-tests.sh — 396/396 accounted, 0 unexpected failures
  • Security leak test: bash tests/security/test_error_msg_leaks.sh — 738+ passed, 0 failures
  • Config fuzz test: bash tests/security/test_govern_json_fuzz.sh — 100/100, 0 crashes
  • naab-x1 end-to-end: cd ~/naab-x1 && naab src/main.naab — exit 0
  • Iterator smoke test: for x in [1,2,3] { print(x) } — works

🤖 Generated with Claude Code

R8 deferred F-7 ("~82 unchecked .asInt()/.asString()") pending compiler
analysis. Deep verification found 85/100+ calls already guarded, bitwise
opcodes don't exist, and OP_DIV/OP_MOD zero-checks are inside type
guards. Actual scope: 11 sites (1 unsafe + 10 defense-in-depth).

Changes:
- READ_CONSTANT_STRING macro: type-guarded constant pool string access
  with bounds check, replaces 8 raw .asString() calls (V-VM-002)
- OP_ITER_NEXT: add isInt() guard before .asInt() — the only truly
  unguarded accessor, returns garbage bits on type mismatch (V-VM-003)
- OP_POLYGLOT: add isDict() guard before .asDictConst() on constant
  pool block info dict (V-VM-004)
- OP_CLOSURE: add isVMClosure() guard before .asVMClosure() on
  constant pool closure (V-VM-005)

Lines 3087/3231 (OP_IMPORT/OP_IMPORT_NAME) also gain bounds checking
by switching from direct constants[arg] to READ_CONSTANT_STRING.

Verified: build 0 errors, 396/396 tests, 738/738 leak checks,
100/100 fuzz cases, naab-x1 exit 0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

NAAb Governance Report

Metric Count
Files checked 16
Passed 16
Failed 0

All governance checks passed!

Generated by NAAb Governance Engine v4.0

@b-macker b-macker merged commit 8a89d96 into master Jun 14, 2026
20 checks passed
@b-macker b-macker deleted the audit/f7-vm-type-guards branch June 14, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant