Skip to content

Commit a793c3f

Browse files
committed
Don't report if msg.value is in a conditional expression
1 parent 456a414 commit a793c3f

File tree

11 files changed

+188
-0
lines changed

11 files changed

+188
-0
lines changed

slither/detectors/statements/msg_value_in_loop.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
from slither.slithir.operations import InternalCall
99
from slither.core.declarations import SolidityVariableComposed, Contract
1010
from slither.utils.output import Output
11+
from slither.slithir.variables.constant import Constant
12+
from slither.core.variables import Variable
13+
from slither.core.expressions.literal import Literal
1114

1215

1316
def detect_msg_value_in_loop(contract: Contract) -> List[Node]:
@@ -37,6 +40,21 @@ def msg_value_in_loop(
3740

3841
for ir in node.all_slithir_operations():
3942
if in_loop_counter > 0 and SolidityVariableComposed("msg.value") in ir.read:
43+
# If we find a conditional expression with msg.value and is compared to 0 we don't report it
44+
if ir.node.is_conditional() and SolidityVariableComposed("msg.value") in ir.read:
45+
compared_to = (
46+
ir.read[1]
47+
if ir.read[0] == SolidityVariableComposed("msg.value")
48+
else ir.read[0]
49+
)
50+
if (
51+
isinstance(compared_to, Constant)
52+
and compared_to.value == 0
53+
or isinstance(compared_to, Variable)
54+
and isinstance(compared_to.expression, Literal)
55+
and str(compared_to.expression.value) == "0"
56+
):
57+
continue
4058
results.append(ir.node)
4159
if isinstance(ir, (InternalCall)):
4260
msg_value_in_loop(ir.function.entry_point, in_loop_counter, visited, results)

tests/e2e/detectors/test_data/msg-value-loop/0.4.25/msg_value_loop.sol

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,38 @@ contract C{
2626
}
2727
}
2828

29+
function good1(address[] memory receivers) public payable {
30+
require(msg.value == 0);
31+
for (uint256 i = 0; i < receivers.length; i++) {
32+
balances[receivers[i]] += 1;
33+
}
34+
}
35+
36+
function good2(address[] memory receivers) public payable {
37+
uint zero = 0;
38+
for (uint256 i = 0; i < receivers.length; i++) {
39+
assert(msg.value == zero);
40+
balances[receivers[i]] += 1;
41+
}
42+
}
43+
44+
function good3(address[] memory receivers) public payable {
45+
for (uint256 i = 0; i < receivers.length; i++) {
46+
if (0 != msg.value) {
47+
revert();
48+
}
49+
balances[receivers[i]] += 1;
50+
}
51+
}
52+
53+
function good4(address[] memory receivers) public payable {
54+
for (uint256 i = 0; i < receivers.length; i++) {
55+
_g();
56+
balances[receivers[i]] += 1;
57+
}
58+
}
59+
60+
function _g() internal {
61+
require(msg.value == 0);
62+
}
2963
}
Binary file not shown.

tests/e2e/detectors/test_data/msg-value-loop/0.5.16/msg_value_loop.sol

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,38 @@ contract C{
2626
}
2727
}
2828

29+
function good1(address[] memory receivers) public payable {
30+
require(msg.value == 0);
31+
for (uint256 i = 0; i < receivers.length; i++) {
32+
balances[receivers[i]] += 1;
33+
}
34+
}
35+
36+
function good2(address[] memory receivers) public payable {
37+
uint zero = 0;
38+
for (uint256 i = 0; i < receivers.length; i++) {
39+
assert(msg.value == zero);
40+
balances[receivers[i]] += 1;
41+
}
42+
}
43+
44+
function good3(address[] memory receivers) public payable {
45+
for (uint256 i = 0; i < receivers.length; i++) {
46+
if (0 != msg.value) {
47+
revert();
48+
}
49+
balances[receivers[i]] += 1;
50+
}
51+
}
52+
53+
function good4(address[] memory receivers) public payable {
54+
for (uint256 i = 0; i < receivers.length; i++) {
55+
_g();
56+
balances[receivers[i]] += 1;
57+
}
58+
}
59+
60+
function _g() internal {
61+
require(msg.value == 0);
62+
}
2963
}

tests/e2e/detectors/test_data/msg-value-loop/0.6.11/msg_value_loop.sol

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,38 @@ contract C{
2626
}
2727
}
2828

29+
function good1(address[] memory receivers) public payable {
30+
require(msg.value == 0);
31+
for (uint256 i = 0; i < receivers.length; i++) {
32+
balances[receivers[i]] += 1;
33+
}
34+
}
35+
36+
function good2(address[] memory receivers) public payable {
37+
uint zero = 0;
38+
for (uint256 i = 0; i < receivers.length; i++) {
39+
assert(msg.value == zero);
40+
balances[receivers[i]] += 1;
41+
}
42+
}
43+
44+
function good3(address[] memory receivers) public payable {
45+
for (uint256 i = 0; i < receivers.length; i++) {
46+
if (0 != msg.value) {
47+
revert();
48+
}
49+
balances[receivers[i]] += 1;
50+
}
51+
}
52+
53+
function good4(address[] memory receivers) public payable {
54+
for (uint256 i = 0; i < receivers.length; i++) {
55+
_g();
56+
balances[receivers[i]] += 1;
57+
}
58+
}
59+
60+
function _g() internal {
61+
require(msg.value == 0);
62+
}
2963
}
Binary file not shown.

tests/e2e/detectors/test_data/msg-value-loop/0.7.6/msg_value_loop.sol

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,38 @@ contract C{
2626
}
2727
}
2828

29+
function good1(address[] memory receivers) public payable {
30+
require(msg.value == 0);
31+
for (uint256 i = 0; i < receivers.length; i++) {
32+
balances[receivers[i]] += 1;
33+
}
34+
}
35+
36+
function good2(address[] memory receivers) public payable {
37+
uint zero = 0;
38+
for (uint256 i = 0; i < receivers.length; i++) {
39+
assert(msg.value == zero);
40+
balances[receivers[i]] += 1;
41+
}
42+
}
43+
44+
function good3(address[] memory receivers) public payable {
45+
for (uint256 i = 0; i < receivers.length; i++) {
46+
if (0 != msg.value) {
47+
revert();
48+
}
49+
balances[receivers[i]] += 1;
50+
}
51+
}
52+
53+
function good4(address[] memory receivers) public payable {
54+
for (uint256 i = 0; i < receivers.length; i++) {
55+
_g();
56+
balances[receivers[i]] += 1;
57+
}
58+
}
59+
60+
function _g() internal {
61+
require(msg.value == 0);
62+
}
2963
}
Binary file not shown.

tests/e2e/detectors/test_data/msg-value-loop/0.8.0/msg_value_loop.sol

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,38 @@ contract C{
2626
}
2727
}
2828

29+
function good1(address[] memory receivers) public payable {
30+
require(msg.value == 0);
31+
for (uint256 i = 0; i < receivers.length; i++) {
32+
balances[receivers[i]] += 1;
33+
}
34+
}
35+
36+
function good2(address[] memory receivers) public payable {
37+
uint zero = 0;
38+
for (uint256 i = 0; i < receivers.length; i++) {
39+
assert(msg.value == zero);
40+
balances[receivers[i]] += 1;
41+
}
42+
}
43+
44+
function good3(address[] memory receivers) public payable {
45+
for (uint256 i = 0; i < receivers.length; i++) {
46+
if (0 != msg.value) {
47+
revert();
48+
}
49+
balances[receivers[i]] += 1;
50+
}
51+
}
52+
53+
function good4(address[] memory receivers) public payable {
54+
for (uint256 i = 0; i < receivers.length; i++) {
55+
_g();
56+
balances[receivers[i]] += 1;
57+
}
58+
}
59+
60+
function _g() internal {
61+
require(msg.value == 0);
62+
}
2963
}
Binary file not shown.

0 commit comments

Comments
 (0)