Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v0.20] Gracefully handle cadence crashes/panics #1364

Merged
merged 8 commits into from
Jan 18, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Handle errors in ParseAndCheckProgram
  • Loading branch information
SupunS committed Jan 17, 2022
commit 66280298e73c37f568bb8de88cd660a656523040
16 changes: 14 additions & 2 deletions runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,19 @@ func hasValidStaticType(value interpreter.Value) bool {
// ParseAndCheckProgram parses the given code and checks it.
// Returns a program that can be interpreted (AST + elaboration).
//
func (r *interpreterRuntime) ParseAndCheckProgram(code []byte, context Context) (*interpreter.Program, error) {
func (r *interpreterRuntime) ParseAndCheckProgram(
code []byte,
context Context,
) (
program *interpreter.Program,
err error,
) {
defer func() {
if recovered, ok := recover().(error); ok {
err = newError(recovered, context)
}
}()

context.InitializeCodesAndPrograms()

storage := r.newStorage(context.Interface)
Expand All @@ -880,7 +892,7 @@ func (r *interpreterRuntime) ParseAndCheckProgram(code []byte, context Context)
checkerOptions,
)

program, err := r.parseAndCheckProgram(
program, err = r.parseAndCheckProgram(
code,
context,
functions,
Expand Down
34 changes: 31 additions & 3 deletions runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6857,6 +6857,7 @@ func TestRuntimeInternalErrors(t *testing.T) {
},
)

require.Error(t, err)
require.ErrorAs(t, err, &Error{})
})

Expand Down Expand Up @@ -6889,6 +6890,7 @@ func TestRuntimeInternalErrors(t *testing.T) {
},
)

require.Error(t, err)
require.ErrorAs(t, err, &Error{})
})

Expand Down Expand Up @@ -6925,13 +6927,13 @@ func TestRuntimeInternalErrors(t *testing.T) {
},
)

require.Error(t, err)
require.ErrorAs(t, err, &Error{})
})

t.Run("contract function", func(t *testing.T) {
t.Parallel()

runtime := newTestInterpreterRuntime()
t.Parallel()

addressValue := Address{
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
Expand Down Expand Up @@ -6963,7 +6965,7 @@ func TestRuntimeInternalErrors(t *testing.T) {
return nil
},
emitEvent: func(_ cadence.Event) error {
return nil;
return nil
},
log: func(message string) {
// panic due to Cadence implementation error
Expand Down Expand Up @@ -7002,6 +7004,32 @@ func TestRuntimeInternalErrors(t *testing.T) {
},
)

require.Error(t, err)
require.ErrorAs(t, err, &Error{})
})

t.Run("parse and check", func(t *testing.T) {

t.Parallel()

script := []byte("pub fun test() {}")
runtimeInterface := &testRuntimeInterface{
setProgram: func(location Location, program *interpreter.Program) error {
panic(errors.New("crash while setting program"))
},
}

nextTransactionLocation := newTransactionLocationGenerator()

_, err := runtime.ParseAndCheckProgram(
script,
Context{
Interface: runtimeInterface,
Location: nextTransactionLocation(),
},
)

require.Error(t, err)
require.ErrorAs(t, err, &Error{})
})
}