Skip to content

Commit

Permalink
Merge pull request #3267 from onflow/supun/force-assignment-resource-…
Browse files Browse the repository at this point in the history
…loss

Fix resource-loss check in dictionary set-key
  • Loading branch information
SupunS committed Apr 18, 2024
2 parents aff3148 + 51739f2 commit e4e8a4b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
10 changes: 7 additions & 3 deletions runtime/interpreter/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -19049,21 +19049,25 @@ func (v *DictionaryValue) SetKey(
locationRange,
)

var existingValue Value
switch value := value.(type) {
case *SomeValue:
innerValue := value.InnerValue(interpreter, locationRange)
existingValue := v.Insert(interpreter, locationRange, keyValue, innerValue)
interpreter.checkResourceLoss(existingValue, locationRange)
existingValue = v.Insert(interpreter, locationRange, keyValue, innerValue)

case NilValue:
_ = v.Remove(interpreter, locationRange, keyValue)
existingValue = v.Remove(interpreter, locationRange, keyValue)

case placeholderValue:
// NO-OP

default:
panic(errors.NewUnreachableError())
}

if existingValue != nil {
interpreter.checkResourceLoss(existingValue, locationRange)
}
}

func (v *DictionaryValue) String() string {
Expand Down
39 changes: 34 additions & 5 deletions runtime/tests/interpreter/resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2927,7 +2927,11 @@ func TestInterpretResourceLoss(t *testing.T) {

t.Parallel()

inter, _, err := parseCheckAndInterpretWithLogs(t, `
t.Run("in callback", func(t *testing.T) {

t.Parallel()

inter := parseCheckAndInterpret(t, `
access(all) resource R {
access(all) let id: String
Expand Down Expand Up @@ -2970,11 +2974,36 @@ func TestInterpretResourceLoss(t *testing.T) {
destroy rl
}
`)
require.NoError(t, err)

_, err = inter.Invoke("main")
RequireError(t, err)
require.ErrorAs(t, err, &interpreter.ResourceLossError{})
_, err := inter.Invoke("main")
RequireError(t, err)
require.ErrorAs(t, err, &interpreter.ResourceLossError{})
})

t.Run("force nil assignment", func(t *testing.T) {

t.Parallel()

inter := parseCheckAndInterpret(t, `
access(all) resource R {
access(all) event ResourceDestroyed()
}
access(all) fun loseResource(_ victim: @R) {
var dict <- { 0: <- victim}
dict[0] <-! nil
destroy dict
}
access(all) fun main() {
loseResource(<- create R())
}
`)

_, err := inter.Invoke("main")
RequireError(t, err)
require.ErrorAs(t, err, &interpreter.ResourceLossError{})
})
}

func TestInterpretPreConditionResourceMove(t *testing.T) {
Expand Down

0 comments on commit e4e8a4b

Please sign in to comment.