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.39] Port internal #143 #2792

Merged
merged 5 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
35 changes: 30 additions & 5 deletions runtime/interpreter/simplecompositevalue.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,25 @@

// ForEachField iterates over all field-name field-value pairs of the composite value.
// It does NOT iterate over computed fields and functions!
func (v *SimpleCompositeValue) ForEachField(_ *Interpreter, f func(fieldName string, fieldValue Value)) {
func (v *SimpleCompositeValue) ForEachField(
f func(fieldName string, fieldValue Value) (resume bool),
) {
for _, fieldName := range v.FieldNames {
fieldValue := v.Fields[fieldName]
f(fieldName, fieldValue)
if !f(fieldName, fieldValue) {
break

Check warning on line 87 in runtime/interpreter/simplecompositevalue.go

View check run for this annotation

Codecov / codecov/patch

runtime/interpreter/simplecompositevalue.go#L87

Added line #L87 was not covered by tests
}
}
}

// Walk iterates over all field values of the composite value.
// It does NOT walk the computed fields and functions!
func (v *SimpleCompositeValue) Walk(interpreter *Interpreter, walkChild func(Value)) {
v.ForEachField(interpreter, func(_ string, fieldValue Value) {
func (v *SimpleCompositeValue) Walk(_ *Interpreter, walkChild func(Value)) {
v.ForEachField(func(_ string, fieldValue Value) (resume bool) {
walkChild(fieldValue)

// continue iteration
return true
})
}

Expand All @@ -98,9 +105,27 @@
}

func (v *SimpleCompositeValue) IsImportable(inter *Interpreter) bool {
// Check type is importable
staticType := v.StaticType(inter)
semaType := inter.MustConvertStaticToSemaType(staticType)
return semaType.IsImportable(map[*sema.Member]bool{})
if !semaType.IsImportable(map[*sema.Member]bool{}) {
return false
}

Check warning on line 113 in runtime/interpreter/simplecompositevalue.go

View check run for this annotation

Codecov / codecov/patch

runtime/interpreter/simplecompositevalue.go#L112-L113

Added lines #L112 - L113 were not covered by tests

// Check all field values are importable
importable := true
v.ForEachField(func(_ string, value Value) (resume bool) {
if !value.IsImportable(inter) {
importable = false
// stop iteration
return false
}

Check warning on line 122 in runtime/interpreter/simplecompositevalue.go

View check run for this annotation

Codecov / codecov/patch

runtime/interpreter/simplecompositevalue.go#L119-L122

Added lines #L119 - L122 were not covered by tests

// continue iteration
return true
})

return importable
}

func (v *SimpleCompositeValue) GetMember(
Expand Down
39 changes: 33 additions & 6 deletions runtime/interpreter/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -15356,16 +15356,22 @@ func (v *CompositeValue) Accept(interpreter *Interpreter, visitor Visitor) {
return
}

v.ForEachField(interpreter, func(_ string, value Value) {
v.ForEachField(interpreter, func(_ string, value Value) (resume bool) {
value.Accept(interpreter, visitor)

// continue iteration
return true
})
}

// Walk iterates over all field values of the composite value.
// It does NOT walk the computed field or functions!
func (v *CompositeValue) Walk(interpreter *Interpreter, walkChild func(Value)) {
v.ForEachField(interpreter, func(_ string, value Value) {
v.ForEachField(interpreter, func(_ string, value Value) (resume bool) {
walkChild(value)

// continue iteration
return true
})
}

Expand All @@ -15384,9 +15390,27 @@ func (v *CompositeValue) StaticType(interpreter *Interpreter) StaticType {
}

func (v *CompositeValue) IsImportable(inter *Interpreter) bool {
// Check type is importable
staticType := v.StaticType(inter)
semaType := inter.MustConvertStaticToSemaType(staticType)
return semaType.IsImportable(map[*sema.Member]bool{})
if !semaType.IsImportable(map[*sema.Member]bool{}) {
return false
}

// Check all field values are importable
importable := true
v.ForEachField(inter, func(_ string, value Value) (resume bool) {
if !value.IsImportable(inter) {
importable = false
// stop iteration
return false
}

// continue iteration
return true
})

return importable
}

func (v *CompositeValue) IsDestroyed() bool {
Expand Down Expand Up @@ -16414,14 +16438,17 @@ func (v *CompositeValue) GetOwner() common.Address {

// ForEachField iterates over all field-name field-value pairs of the composite value.
// It does NOT iterate over computed fields and functions!
func (v *CompositeValue) ForEachField(gauge common.MemoryGauge, f func(fieldName string, fieldValue Value)) {
func (v *CompositeValue) ForEachField(
gauge common.MemoryGauge,
f func(fieldName string, fieldValue Value) (resume bool),
) {

err := v.dictionary.Iterate(func(key atree.Value, value atree.Value) (resume bool, err error) {
f(
resume = f(
string(key.(StringAtreeValue)),
MustConvertStoredValue(gauge, value),
)
return true, nil
return
})
if err != nil {
panic(errors.NewExternalError(err))
Expand Down
143 changes: 143 additions & 0 deletions runtime/program_params_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1141,4 +1141,147 @@ func TestRuntimeTransactionParameterTypeValidation(t *testing.T) {
var entryPointErr *InvalidEntryPointArgumentError
require.ErrorAs(t, err, &entryPointErr)
})

t.Run("Invalid private cap in struct", func(t *testing.T) {
t.Parallel()

contracts := map[common.AddressLocation][]byte{
{
Address: common.MustBytesToAddress([]byte{0x1}),
Name: "C",
}: []byte(`
pub contract C {
pub struct S {
pub let cap: Capability

init(cap: Capability) {
self.cap = cap
}
}
}
`),
}

script := `
import C from 0x1

transaction(arg: C.S) {}
`

address := common.MustBytesToAddress([]byte{0x1})

path, err := cadence.NewPath(common.PathDomainPrivate, "foo")
require.NoError(t, err)

capability := cadence.NewPathCapability(
cadence.Address(address),
path,
cadence.NewReferenceType(false, cadence.AuthAccountType{}),
)

arg := cadence.Struct{
StructType: &cadence.StructType{
Location: common.AddressLocation{
Address: address,
Name: "C",
},
QualifiedIdentifier: "C.S",
Fields: []cadence.Field{
{
Identifier: "cap",
Type: &cadence.CapabilityType{},
},
},
},
Fields: []cadence.Value{
capability,
},
}

err = executeTransaction(t, script, contracts, arg)
expectRuntimeError(t, err, &ArgumentNotImportableError{})
})

t.Run("Invalid private cap in array", func(t *testing.T) {
t.Parallel()

script := `
transaction(arg: [AnyStruct]) {}
`

address := common.MustBytesToAddress([]byte{0x1})

path, err := cadence.NewPath(common.PathDomainPrivate, "foo")
require.NoError(t, err)

capability := cadence.NewPathCapability(
cadence.Address(address),
path,
cadence.NewReferenceType(false, cadence.AuthAccountType{}),
)

arg := cadence.Array{
ArrayType: cadence.NewVariableSizedArrayType(cadence.AnyStructType{}),
Values: []cadence.Value{
capability,
},
}

err = executeTransaction(t, script, nil, arg)
expectRuntimeError(t, err, &ArgumentNotImportableError{})
})

t.Run("Invalid private cap in optional", func(t *testing.T) {
t.Parallel()

script := `
transaction(arg: AnyStruct?) {}
`

address := common.MustBytesToAddress([]byte{0x1})

path, err := cadence.NewPath(common.PathDomainPrivate, "foo")
require.NoError(t, err)

capability := cadence.NewPathCapability(
cadence.Address(address),
path,
cadence.NewReferenceType(false, cadence.AuthAccountType{}),
)

arg := cadence.NewOptional(capability)

err = executeTransaction(t, script, nil, arg)
expectRuntimeError(t, err, &ArgumentNotImportableError{})
})

t.Run("Invalid private cap in dictionary value", func(t *testing.T) {
t.Parallel()

script := `
transaction(arg: {String: AnyStruct}) {}
`

address := common.MustBytesToAddress([]byte{0x1})

path, err := cadence.NewPath(common.PathDomainPrivate, "foo")
require.NoError(t, err)

capability := cadence.NewPathCapability(
cadence.Address(address),
path,
cadence.NewReferenceType(false, cadence.AuthAccountType{}),
)

arg := cadence.NewDictionary([]cadence.KeyValuePair{
{
Key: cadence.String("cap"),
Value: capability,
},
})

err = executeTransaction(t, script, nil, arg)
expectRuntimeError(t, err, &ArgumentNotImportableError{})
})

}
Loading
Loading