Skip to content

Commit 6b1261c

Browse files
authored
CRE-1613: Fix internal errors passed from WASM host to guest and add a standard test for it (#1745)
* CRE-1613: Fix internal errors passed from WASM host to guest and add a standard test for it * Fix a typo
1 parent 2df013c commit 6b1261c

File tree

4 files changed

+51
-2
lines changed

4 files changed

+51
-2
lines changed

pkg/workflows/wasm/host/internal/rawsdk/helpers_wasip1.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ func await[I, O proto.Message](input I, output O, fn awaitFn) {
197197
bytes := fn(mptr, mlen, responsePtr, responseLen)
198198

199199
if bytes < 0 {
200-
SendError(errors.New("awaitCapabilities returned an error"))
200+
response = response[:-bytes]
201+
SendError(fmt.Errorf("awaitCapabilities returned an error %s", string(response)))
201202
}
202203

203204
if proto.Unmarshal(response[:bytes], output) != nil {

pkg/workflows/wasm/host/module.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,9 @@ func truncateWasmWrite(caller *wasmtime.Caller, src []byte, ptr int32, size int3
10661066
src = src[:size]
10671067
}
10681068

1069-
return write(memory, src, ptr, size)
1069+
// truncateWasmWrite is only called for returning error strings
1070+
// Therefore, we need to return the negated bytes written to indicate the failure to the guest.
1071+
return -write(memory, src, ptr, size)
10701072
}
10711073

10721074
// write copies the given src byte slice into the memory at the given pointer and max size.

pkg/workflows/wasm/host/standard_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,37 @@ func TestStandardCapabilityCallsAreAsync(t *testing.T) {
118118
assert.Equal(t, "truefalse", result)
119119
}
120120

121+
func TestStandardHostWasmWriteErrorsAreRespected(t *testing.T) {
122+
t.Parallel()
123+
mockExecutionHelper := NewMockExecutionHelper(t)
124+
mockExecutionHelper.EXPECT().GetNodeTime().RunAndReturn(func() time.Time {
125+
return time.Now()
126+
}).Maybe()
127+
mockExecutionHelper.EXPECT().GetWorkflowExecutionID().Return("id")
128+
mockExecutionHelper.EXPECT().CallCapability(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, request *sdk.CapabilityRequest) (*sdk.CapabilityResponse, error) {
129+
// In this test the response from the capability is successful,
130+
// but the WASM didn't provide a large enough buffer to fit it
131+
// 500 MB will suffice for the overflow on writes.
132+
133+
tooLargeResponse := make([]byte, 500000000)
134+
135+
// Since the bytes in the payload shouldn't be read, we don't need a valid proto
136+
payload := &anypb.Any{
137+
TypeUrl: "fake",
138+
Value: tooLargeResponse,
139+
}
140+
141+
return &sdk.CapabilityResponse{Response: &sdk.CapabilityResponse_Payload{Payload: payload}}, nil
142+
})
143+
144+
m := makeTestModule(t)
145+
request := triggerExecuteRequest(t, 0, &basictrigger.Outputs{CoolOutput: anyTestTriggerValue})
146+
errStr := executeWithError(t, m, request, mockExecutionHelper)
147+
148+
// Use Contains instead of Equal for flexibility, as languages have different conventions for errors.
149+
require.Contains(t, errStr, ResponseBufferTooSmall)
150+
}
151+
121152
func TestStandardModeSwitch(t *testing.T) {
122153
t.Parallel()
123154
t.Run("successful mode switch", func(t *testing.T) {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package main
2+
3+
import (
4+
"github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/protoc/pkg/test_capabilities/basicaction"
5+
"github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host/internal/rawsdk"
6+
"github.com/smartcontractkit/chainlink-protos/cre/go/sdk"
7+
)
8+
9+
func main() {
10+
input := &basicaction.Inputs{InputThing: true}
11+
rId := rawsdk.DoRequestAsync("[email protected]", "PerformAction", sdk.Mode_MODE_DON, input)
12+
13+
rawsdk.Await(rId, &basicaction.Outputs{})
14+
rawsdk.SendResponse("should not get here as Await sends error on errors...")
15+
}

0 commit comments

Comments
 (0)