crytic / crytic/slither

[Bug]: When variable is reused in two multi-return assignments, original tuple index is reused

Open
#1,913 4 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Python
Stars
6.4k
Forks
1.1k
PR merge metrics
No merged PRs in 30d

Description

### Describe the issue:

When a variable is used to store a result of a multi-return function call and then later used to store the result of a different multi-return function call, the index of the first UNPACK operation is used for the second UNPACK. Instead, the index of the second UNPACK should be based on where the variable was listed on the lhs of the assignment.

### Code example to reproduce the issue:

```
contract Test {
function threeRet(int z) internal returns(int, int, int) {
return (1,2,3);
}
function twoRet(int z) internal returns(int, int) {
return (3,4);
}

function test() external returns(int) {
(int a, int b, int c) = threeRet(3);
(a, c) = twoRet(b);
return b;
}
}
```

### Version:

0.9.3

### Relevant log output:

```shell
INFO:Printers:Contract Test
Function Test.threeRet(int256) (*)
Expression: (1,2,3)
IRs:
RETURN 1,2,3
Function Test.twoRet(int256) (*)
Expression: (3,4)
IRs:
RETURN 3,4
Function Test.test() (*)
Expression: (a,b,c) = threeRet(3)
IRs:
TUPLE_0(int256,int256,int256) = INTERNAL_CALL, Test.threeRet(int256)(3)
a(int256)= UNPACK TUPLE_0 index: 0
b(int256)= UNPACK TUPLE_0 index: 1
c(int256)= UNPACK TUPLE_0 index: 2
Expression: (a,c) = twoRet(b)
IRs:
TUPLE_1(int256,int256) = INTERNAL_CALL, Test.twoRet(int256)(b)
a(int256)= UNPACK TUPLE_1 index: 0
c(int256)= UNPACK TUPLE_1 index: 2
Expression: b
IRs:
RETURN b

Note that we unpack index 2 into `c` for the second call, but the result of `twoRet` doesn't even have a component with index 2.
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.