feat(ir): add EnvValue::RuntimeExpression variant to prevent $[] in step env#1082
Conversation
…guard Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
|
/rust-review |
|
✅ Rust PR Reviewer completed successfully! |
🔍 Rust PR ReviewSummary: Solid design with one latent bug in the hoist-collection pass — worth fixing before merging to prevent a silent footgun for future callers. Findings🐛 Bugs / Logic Issues
The hoist-collection pass only matches for v in env.values() {
if let EnvValue::RuntimeExpression(body) = v { ... } // top-level only
}But The same gap applies to Both fixes point the same way: either recurse into (No existing code triggers this today since ✅ What Looks Good
|
|
@copilot address feedback |
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
Addressed the rust-review finding: |
|
/rust-review |
|
✅ Rust PR Reviewer completed successfully! |
🔍 Rust PR ReviewSummary: Looks good — solid structural fix with comprehensive tests. One minor guard gap worth noting. Findings
|
…licit-var precedence Addresses rust-review feedback on PR #1082: - reject_runtime_expr_literal_in_step_env now also rejects a RawYamlScalar(String) carrying a \$[ ... ] runtime expression, which previously bypassed string lowering and slipped past the Literal-only check. - Add tests for the RawYamlScalar guard and for the explicit-job-variable -wins-over-hoist precedence path in collect_runtime_expr_hoists. - Document the RawYamlScalar coverage in docs/ir.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/rust-review |
|
✅ Rust PR Reviewer completed successfully! |
🔍 Rust PR ReviewSummary: Looks good — the design is sound and test coverage is thorough. One genuine bug in the Findings🐛 Bugs / Logic Issues
|
…body-injection note Addresses rust-review feedback on PR #1082: - reject_runtime_expr_in_concat now also rejects a RawYamlScalar(String) carrying a \$[ ... ] runtime expression, mirroring the top-level guard; previously such a scalar concatenated verbatim into the step env (the exact footgun being patched). - Add a test for the Concat RawYamlScalar rejection and a test that a RuntimeExpression in a TaskStep env is hoisted (parity with BashStep). - Document on EnvValue::runtime_expression that the body is interpolated verbatim into \$[ {body} ] (compiler-internal use; reject ] if untrusted text is ever routed through it). - Update docs/ir.md for the nested-Concat RawYamlScalar rejection. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
ADO evaluates
$[ ... ]runtime expressions only in job-levelvariables:andcondition:fields — never in stepenv:, where the literal string is passed verbatim. This has silently broken pipelines (build #612528, #1076). The compiler now makes that mistake structurally impossible.New variant —
EnvValue::RuntimeExpression(String)insrc/compile/ir/env.rs, carrying the expression body (no$[ ]wrapper):Auto-hoist on lowering (
lower_job):RuntimeExpressionin a job's stepenv:is lifted to a generated job variableAwRtExpr_<sha256[..12]>: $[ body ].env:value lowers to a$(AwRtExpr_…)macro reference. The name is content-derived so the hoist pass and env lowering agree without a shared map; identical expressions collapse to one variable, and an explicit job var of the same name is never clobbered.Guard —
lower_bash/lower_taskreject anyEnvValue::Literalcontaining$[, with an error pointing toRuntimeExpression. Mirrors the existingassert_no_dollar_bracket_in_step_envtest helper, now enforced at lower time.Other —
graph.rstreats the variant as carrying noOutputRef(no edges).RuntimeExpressionis only valid at the top level of a stepenv:value: nesting it insideCoalesceorConcatis rejected at lower time. The hoist pass walks only the top level of each step env (andConcatlowers its children verbatim), so a nested occurrence would otherwise leave a dangling$(AwRtExpr_…)macro; aLiteralcarrying$[nested inside aConcatis rejected for the same reason. Docs updated indocs/ir.md.No existing step-env violations remain in the tree — prior bugs were already patched via manual hoists; this variant is preventive.
Test plan
cargo test— added unit tests inenv.rs(constructor) andlower.rs(macro emission, hoist-to-variable, dedup, literal-$[rejection,RuntimeExpression/$[-literal nested-Concatrejection including nestedConcat, and a positive test that valid macro-formConcatchildren still lower); full suite passes.cargo clippy --all-targets --all-featuresclean.