Repository navigation
fix(hy-check): close place-call, paren-callee, and A3/const bypasses (fixes #500) - #501
Open
o2splatform-cmyk wants to merge 13 commits into
Open
o2splatform-cmyk wants to merge 13 commits into
o2splatform-cmyk wants to merge 13 commits into
Conversation
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #500.
Problem & Root Cause
On
main(91ab10305b0a603516c073b9378243c76a04f002), four closely related AST traversal and call-resolution gaps inhy-checkallow accepted Tier-0 programs to trigger concurrent map races (HYB-E3003/HYB-E3102), mutateconstcomposites (HYB-E3006), or pass invalid builtin arguments (HYB-E2005) with0diagnostics:Stmt::Assigntarget places (PlaceKind::Index,PlaceKind::Field,PlaceKind::AddrOf) are dropped bywalk::own_calls,walk::own_fnlits, andbuiltins::check_place_builtin_args:walk::own_calls(walk.rs:527-537) only recursed into a single outerPlaceKind::Index { index, .. }and never recursed intobaseacross nestedPlaceKind::Index,PlaceKind::Field, orPlaceKind::AddrOf. Consequently, calls inside assignment targets such asgrid[copy(dst, src)][0] = 1,box[0].items[(fn() int { m["k"] = 9; return 0 })()] = 1, orgrid[delete(42, "k")][0] = 1bypassedcopymay-share freeze tracking (HYB-E3003),constwrite checks (HYB-E3006), A3 map-slot loan invalidation (HYB-E3102), and builtin argument validation (HYB-E2005).walk::own_fnlits(walk.rs:601-605) did not visitStmt::Assign { targets, .. }at all, andbuiltins::check_place_builtin_args(builtins.rs:171-182) only inspectedindexwithout recursing intobase.(copy)(dst, src),(delete)(m, "k"), and(corrupt)(m)bypassresolve_calland interprocedural mutation helpers:loans.rsmatched bareExpr::Ident/Expr::Fieldoncr.calleewithout strippingExpr::Paren. Wrapping a builtin or mutating function in parentheses bypassedResolved::Copy,Resolved::Delete,call_mutates_param,collect_mutation_roots, andcall_mutates_const_param.Expr::Parenoncr.callee, selector bases insideExpr::Field { base, .. }must also unwrap parentheses so(fmt).println(m)continues to matchA3_PURE_PKGSwithout false positives.HYB-E3102) and interproceduralconstchecks (HYB-E3006) miss closure callees, method callees, inlineFnLitcallees, call-returned closures, andStmt::Switch/Stmt::Selectclosure bodies:process_call(loans.rs),Resolved::Fnonly checkedself.fns.get(&name)(skipping local closure bindingsf(m)that mutate their map parameter),Resolved::Methoddid not check method bodies that mutate the receiver or map arguments during a live&m[k]slot loan, andResolved::Noneskipped inline(fn(d map[string]int) { d["b"] = 2 })(m), slice/map-indexed closure calleesfns[0](m), and call-returned closure calleesmake_mutator()(m).LexicalStructMap), pointer receivers (*Right), call/method return types, and shadowing non-struct inner bindings so a read-onlyRight.touchnever collides with a mutatingWrong.touch.stmt_mutates_param,collect_mutation_roots, andstmt_mutates_const_paramhand-rolled partialFnLitextractors that missedStmt::SwitchandStmt::Select; unifying them onwalk::own_fnlitscloses all statement positions whilewalk::own_callsincludesForKind::Iteratefor interprocedural callers (withChecker::check_stmthandlingStmt::Forheaders directly so top-levelForKind::Iteratecalls are not double-processed).copy,delete,append,clear,len,cap,new,make,some,ok,err) inloans.rs:copy := fn(d map[string]int) { d["b"] = 2 }orfn len(d map[string]int) { d["k"] = 9 }),resolve_calland the builtin exemptions inloans.rspreviously classified the call as the pure/builtin operation rather than a user-defined or closure call. Guarding builtin recognition with!self.is_builtin_shadowed_by_local(st, name)and!self.fns.contains_key(name)routes shadowed calls through normal A3/const/freeze analysis.Verification
compiler/crates/hy-check/tests/place_call_and_a3_callee_soundness.rscovering every soundness bypass (HYB-E3003,HYB-E3006,HYB-E3102,HYB-E2005) alongside positive controls (Verdict::Acceptfor read-only closures, read-only methods with same-named mutating methods on another struct, and parenthesized(fmt).println(m)).91ab10305b0a603516c073b9378243c76a04f002:cargo test -p hy-check:560/560passed across all42suites (0failures).python3 tools/corpus_harness.py:60/60verdict agreement (tripwire: not fired).python3 tools/check_conflict_markers.py&python3 tools/check_test_registration.py:OK.