Skip to content

fix: follow-up compiler fixes from the 0.14 audit - #461

Open
mr-zwets wants to merge 1 commit into
nextfrom
fix/compiler-audit-remaining
Open

mr-zwets wants to merge 1 commit into
nextfrom
fix/compiler-audit-remaining

Conversation

@mr-zwets

@mr-zwets mr-zwets commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Opened on behalf of Mathieu G. (mr-zwets), written by Claude Opus 5.5.

Replaces #459, which was opened from the wrong branch by mistake.

Follow-up to the 0.14 audit, meant to land after the 0.14.0 release: the important compiler findings are fixed in #463, #464, #465 and #466, and this PR holds the smaller ones that were left out to keep the release's scope small. Rebased on next, without the parts those PRs cover.

Changes

  • Compiler options passed as undefined: { enforceLocktimeGuard: config.x } with x unset disabled the locktime guard (and the same for enforceFunctionParameterTypes), while the artifact recorded compiler.options: {}, which reads as the defaults. Options now fall back to their defaults, and only the known options are recorded (unknown keys and the files map were copied into the artifact).
  • Stale stack slots: after a reassignment outside a loop or branch, the old value stays on the stack under the same name. It is now made anonymous, so a mismatch between where the symbol table records a final use and where code generation reads the variable (the class of fix: fix slice() variable final-use handling #464 and fix: fix init-reassign for-loop bug #466) is a compile error instead of a stale read. No bytecode changes. As a side effect, console.log shows the current value of a reassigned variable after its final use, instead of the old one.
  • Tuple destructuring: bytes a, bytes b = a.split(1); crashed with an internal error (no location); it is now an UndefinedReferenceError, like int a = a + 1;.

No release notes yet, since the 0.14 section will be closed by then. Suggested lines for the next release:

  • 🐛 Fix bug where compiler options passed as undefined were disabled instead of using their default value, and unknown compiler options were included in the artifact.
  • 🐛 Fix bug where using a newly declared variable on the right-hand side of its own tuple destructuring caused an internal compiler error instead of an UndefinedReferenceError.
  • 🐛 Fix bug where console.log showed an outdated value for a reassigned variable after its final use.

Tests

  • A test that no variable is read after its final use, for every valid contract file and for a contract that reads the same variable in every child of each expression node type.
  • Compiler option tests (undefined options still inject the guard, unknown keys are dropped) and a tuple error fixture.
  • SDK: console.log of a reassigned variable after its final use.

The option, tuple and console.log tests fail on the current next. Recompiling the fixtures gives unchanged bytecode.

yarn build, yarn test, yarn lint and yarn spellcheck pass.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cashscript Ready Ready Preview Sep 29, 2026 9:58am UTC

Request Review

@codecov

codecov Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.26%. Comparing base (625d844) to head (37f664f).

Additional details and impacted files
@@            Coverage Diff             @@
##             next     #461      +/-   ##
==========================================
+ Coverage   89.23%   89.26%   +0.02%     
==========================================
  Files          61       61              
  Lines        5074     5087      +13     
  Branches      949      951       +2     
==========================================
+ Hits         4528     4541      +13     
  Misses        421      421              
  Partials      125      125              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

- Use the default value for compiler options that are passed as undefined
  (e.g. `{ enforceLocktimeGuard: config.x }` with `x` unset), which disabled
  the locktime guard or parameter type checks, and only record the known
  options in the artifact (unknown keys and the `files` map were copied in).
- Make the old stack slot of a variable anonymous when it is reassigned
  outside of a loop or branch, so a mismatch between where the symbol table
  records a final use and where code generation reads the variable (like
  the ones fixed in #464 and #466) is a compile error instead of reading an
  outdated value. This does not change any bytecode, and makes console.log
  show the current value of a reassigned variable after its final use.
- Declare new tuple destructuring targets after visiting the right-hand side,
  so using one of them there is an UndefinedReferenceError instead of an
  internal error.

Adds a test that no variable is read after its final use, for every valid
contract file and for a contract that reads the same variable in every
child of each expression node type.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mr-zwets
mr-zwets force-pushed the fix/compiler-audit-remaining branch from 49bb0ef to 37f664f Compare September 29, 2026 09:58
@mr-zwets mr-zwets changed the title fix: for-loop init and slice() miscompiles, and other compiler findings from the 0.14 audit fix: follow-up compiler fixes from the 0.14 audit Sep 29, 2026
@github-actions

Copy link
Copy Markdown

Pull request stats

Source Tests Total Net Share
Compiler (cashc) +33 −7 +154 −1 +187 −8 +179 92%
SDK (cashscript) +16 −0 +16 −0 +16 8%
Total +33 −7 +170 −1 +203 −8 +195 100%

Reviewable churn: 211 lines (net +195), version bumps and generated files excluded.
Test lines per line of source: 4.28.
Comments: 5 of 29 added source lines, 17%.

New files: 2

  • packages/cashc/test/compiler/UndefinedReferenceError/tuple_target_used_in_own_declaration.cash
  • packages/cashc/test/generation/final-use.test.ts

Package source changed without an update to website/docs/releases/release-notes.md.

This branch was successfully deployed

1 active deployment
Preview — 37f664fd Deployed Sep 29, 2026 by vercel[bot]
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