Skip to content

Commit

Permalink
Reject non-storable transaction/script arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminkvm authored and turbolent committed Aug 10, 2020
1 parent 8940034 commit 5185205
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 0 deletions.
34 changes: 34 additions & 0 deletions runtime/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,37 @@ func (e *ScriptReturnTypeNotStorableError) Error() string {
e.Type.QualifiedString(),
)
}

// ScriptParamterTypeNotStorableError is an error that is reported for
// script parameter types that are not storable.
//
// For example, the type `Int` is a storable type,
// whereas a function type is not.

type ScriptParameterTypeNotStorableError struct {
Type sema.Type
}

func (e *ScriptParameterTypeNotStorableError) Error() string {
return fmt.Sprintf(
"parameter type is non-storable type: `%s`",
e.Type.QualifiedString(),
)
}

// TransactionParamterTypeNotStorableError is an error that is reported for
// transaction parameter types that are not storable.
//
// For example, the type `Int` is a storable type,
// whereas a function type is not.

type TransactionParameterTypeNotStorableError struct {
Type sema.Type
}

func (e *TransactionParameterTypeNotStorableError) Error() string {
return fmt.Sprintf(
"parameter type is non-storable type: `%s`",
e.Type.QualifiedString(),
)
}
28 changes: 28 additions & 0 deletions runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ func (r *interpreterRuntime) ExecuteScript(
}
epSignature := invokableType.InvocationFunctionType()

// Ensure entrypoint return type is storable
storableResults := map[*sema.Member]bool{}
if _, isVoid := epSignature.ReturnTypeAnnotation.Type.(*sema.VoidType); !isVoid {
if !epSignature.ReturnTypeAnnotation.Type.IsStorable(storableResults) {
Expand All @@ -159,6 +160,19 @@ func (r *interpreterRuntime) ExecuteScript(
}
}

// Ensure entrypoint parameters type is storable
if len(epSignature.Parameters) > 0 {
for _, param := range epSignature.Parameters {
if _, isVoid := param.TypeAnnotation.Type.(*sema.VoidType); !isVoid {
if !param.TypeAnnotation.Type.IsStorable(storableResults) {
return nil, &ScriptParameterTypeNotStorableError{
Type: param.TypeAnnotation.Type,
}
}
}
}
}

value, inter, err := r.interpret(
location,
runtimeInterface,
Expand Down Expand Up @@ -314,6 +328,20 @@ func (r *interpreterRuntime) ExecuteTransaction(
})
}

// Ensure parameter types are storable
storableResults := map[*sema.Member]bool{}
if len(transactionType.Parameters) > 0 {
for _, param := range transactionType.Parameters {
if _, isVoid := param.TypeAnnotation.Type.(*sema.VoidType); !isVoid {
if !param.TypeAnnotation.Type.IsStorable(storableResults) {
return newError(&TransactionParameterTypeNotStorableError{
Type: param.TypeAnnotation.Type,
})
}
}
}
}

transactionAuthorizerCount := len(transactionType.PrepareParameters)
if authorizerCount != transactionAuthorizerCount {
return newError(InvalidTransactionAuthorizerCountError{
Expand Down
42 changes: 42 additions & 0 deletions runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,24 @@ func TestRuntimeTransactionWithArguments(t *testing.T) {
},
expectedLogs: []string{"42", `"foo"`},
},

{
label: "Invalid non-storable argument type",
script: `
transaction(x: ((Int): Int)) {
execute {
x(0)
}
}
`,
args: [][]byte{
jsoncdc.MustEncode(cadence.NewInt(42)),
},
check: func(t *testing.T, err error) {
assert.Error(t, err)
assert.IsType(t, &TransactionParameterTypeNotStorableError{}, errors.Unwrap(err))
},
},
{
label: "Invalid bytes",
script: `
Expand Down Expand Up @@ -1852,6 +1870,30 @@ func TestScriptReturnTypeNotStorableError(t *testing.T) {
assert.IsType(t, &ScriptReturnTypeNotStorableError{}, err)
}

func TestScriptParameterTypeNotStorableError(t *testing.T) {

t.Parallel()

runtime := NewInterpreterRuntime()

script := []byte(`
pub fun main(x: ((): Int)) {
return
}
`)

runtimeInterface := &testRuntimeInterface{
getSigningAccounts: func() []Address {
return []Address{{42}}
},
}

nextTransactionLocation := newTransactionLocationGenerator()

_, err := runtime.ExecuteScript(script, nil, runtimeInterface, nextTransactionLocation())
assert.IsType(t, &ScriptParameterTypeNotStorableError{}, err)
}

func TestRuntimeSyntaxError(t *testing.T) {

t.Parallel()
Expand Down

0 comments on commit 5185205

Please sign in to comment.