Skip to content

Commit

Permalink
Merge pull request #3404 from onflow/bastian/prevent-nested-storage-r…
Browse files Browse the repository at this point in the history
…eference
  • Loading branch information
turbolent authored Jun 10, 2024
2 parents 58c36c5 + 8f25dac commit b7981e5
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
7 changes: 7 additions & 0 deletions runtime/interpreter/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -20601,6 +20601,13 @@ func (v *StorageReferenceValue) dereference(interpreter *Interpreter, locationRa
return nil, nil
}

if reference, isReference := referenced.(ReferenceValue); isReference {
panic(NestedReferenceError{
Value: reference,
LocationRange: locationRange,
})
}

if v.BorrowedType != nil {
staticType := referenced.StaticType(interpreter)

Expand Down
68 changes: 68 additions & 0 deletions runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10842,3 +10842,71 @@ func TestRuntimeAccountEntitlementEscalation(t *testing.T) {
})
require.ErrorAs(t, err, &interpreter.InvalidMemberReferenceError{})
}

func TestRuntimeAccountStorageBorrowEphemeralReferenceValue(t *testing.T) {

t.Parallel()

addressValue := Address{
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
}

runtime := NewTestInterpreterRuntime()

contract := []byte(`
access(all) contract C {
init() {
let pubAccount = getAccount(0x01)
self.account.storage.save(pubAccount as AnyStruct, to: /storage/account)
let authAccount = self.account.storage.borrow<auth(Storage) &(&Account)>(from: /storage/account)!
}
}
`)

deploy := DeploymentTransaction("C", contract)

accountCodes := map[Location][]byte{}
var events []cadence.Event

runtimeInterface := &TestRuntimeInterface{
OnGetCode: func(location Location) (bytes []byte, err error) {
return accountCodes[location], nil
},
Storage: NewTestLedger(nil, nil),
OnGetSigningAccounts: func() ([]Address, error) {
return []Address{addressValue}, nil
},
OnResolveLocation: NewSingleIdentifierLocationResolver(t),
OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
return accountCodes[location], nil
},
OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
accountCodes[location] = code
return nil
},
OnCreateAccount: func(payer Address) (address Address, err error) {
return addressValue, nil
},
OnEmitEvent: func(event cadence.Event) error {
events = append(events, event)
return nil
},
}

nextTransactionLocation := NewTransactionLocationGenerator()

err := runtime.ExecuteTransaction(
Script{
Source: deploy,
},
Context{
Interface: runtimeInterface,
Location: nextTransactionLocation(),
},
)
RequireError(t, err)

var nestedReferenceErr interpreter.NestedReferenceError
require.ErrorAs(t, err, &nestedReferenceErr)
}

0 comments on commit b7981e5

Please sign in to comment.