From 8f25dac6ae00ce82f56da400e219ab9f6f4e304c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Fri, 7 Jun 2024 14:33:26 -0700 Subject: [PATCH] prevent storage reference to another reference --- runtime/interpreter/value.go | 7 ++++ runtime/runtime_test.go | 68 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go index 6f36d14146..84e39ca244 100644 --- a/runtime/interpreter/value.go +++ b/runtime/interpreter/value.go @@ -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) diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index 5972980f49..8f6eeeacd7 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -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(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) +}