From 2227441f7dbcc5a849c5634e0d2f537c500c4740 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 24 Oct 2025 09:52:37 -0400 Subject: [PATCH] don't cache unknown function results The CheckPrior function results validation did not take into account unknown values, because unknown values were not originally allowed in the plugin protocol from which this check was adapted. The test is simple, in that we can just reverse the check which originally didn't allow this change in value. Provider function return values types are defined by the protocol, and should be validated at that call site. The CheckPrior code paths should only be used for the exact purpose of detecting invalid changes in the return value between successive phases of execution. --- internal/lang/function_results.go | 10 ++++++++++ internal/lang/function_results_test.go | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/lang/function_results.go b/internal/lang/function_results.go index 6d4f97e700..2b7b23afb8 100644 --- a/internal/lang/function_results.go +++ b/internal/lang/function_results.go @@ -51,6 +51,16 @@ func (f *FunctionResults) CheckPrior(name string, args []cty.Value, result cty.V // CheckPriorProvider compares the provider function call against any cached // results, and returns an error if the result does not match a prior call. func (f *FunctionResults) CheckPriorProvider(provider addrs.Provider, name string, args []cty.Value, result cty.Value) error { + // Don't cache unknown values. We could technically store types and + // refinements for validation, but we don't currently have a way to + // serialize those in the plan. Unknowns are also handled much more + // gracefully throughout the evaluation system, whereas invalid data is + // harder to trace back to the source since it's usually only visible due to + // unexpected side-effects. + if !result.IsKnown() { + return nil + } + argSum := sha256.New() if !provider.IsZero() { diff --git a/internal/lang/function_results_test.go b/internal/lang/function_results_test.go index da5715738b..56e44244c6 100644 --- a/internal/lang/function_results_test.go +++ b/internal/lang/function_results_test.go @@ -72,7 +72,7 @@ func TestFunctionCache(t *testing.T) { result: cty.False, }, // result changed from unknown => false - expectErr: true, + expectErr: false, }, { first: testCall{ @@ -172,6 +172,9 @@ func TestFunctionCache(t *testing.T) { if err != nil && !test.expectErr { t.Fatal(err) } + if err == nil && test.expectErr { + t.Fatal("expected error") + } // reload the data to ensure we validate identically newResults := NewFunctionResultsTable(results.GetHashes())