Skip to content

Commit 1f8f1a3

Browse files
authored
Merge pull request #11484 from ethereum/fix-unreachable-code-anaysis
Fix revert pruner modifying function flows wrong
2 parents c92fc75 + 8da5d6a commit 1f8f1a3

File tree

9 files changed

+35
-3
lines changed

9 files changed

+35
-3
lines changed

docs/control-structures.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ this nonsensical example::
4444
// SPDX-License-Identifier: GPL-3.0
4545
pragma solidity >=0.4.22 <0.9.0;
4646

47+
// This will report a warning
4748
contract C {
4849
function g(uint a) public pure returns (uint ret) { return a + f(); }
4950
function f() internal pure returns (uint ret) { return g(7) + f(); }

libsolidity/analysis/ControlFlowBuilder.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,37 +260,51 @@ bool ControlFlowBuilder::visit(PlaceholderStatement const&)
260260

261261
bool ControlFlowBuilder::visit(FunctionCall const& _functionCall)
262262
{
263+
solAssert(!!m_revertNode, "");
263264
solAssert(!!m_currentNode, "");
264265
solAssert(!!_functionCall.expression().annotation().type, "");
265266

266267
if (auto functionType = dynamic_cast<FunctionType const*>(_functionCall.expression().annotation().type))
267268
switch (functionType->kind())
268269
{
269270
case FunctionType::Kind::Revert:
270-
solAssert(!!m_revertNode, "");
271271
visitNode(_functionCall);
272272
_functionCall.expression().accept(*this);
273273
ASTNode::listAccept(_functionCall.arguments(), *this);
274+
274275
connect(m_currentNode, m_revertNode);
276+
275277
m_currentNode = newLabel();
276278
return false;
277279
case FunctionType::Kind::Require:
278280
case FunctionType::Kind::Assert:
279281
{
280-
solAssert(!!m_revertNode, "");
281282
visitNode(_functionCall);
282283
_functionCall.expression().accept(*this);
283284
ASTNode::listAccept(_functionCall.arguments(), *this);
285+
284286
connect(m_currentNode, m_revertNode);
287+
285288
auto nextNode = newLabel();
289+
286290
connect(m_currentNode, nextNode);
287291
m_currentNode = nextNode;
288292
return false;
289293
}
290294
case FunctionType::Kind::Internal:
291295
{
296+
visitNode(_functionCall);
297+
_functionCall.expression().accept(*this);
298+
ASTNode::listAccept(_functionCall.arguments(), *this);
299+
292300
m_currentNode->functionCalls.emplace_back(&_functionCall);
293-
break;
301+
302+
auto nextNode = newLabel();
303+
304+
connect(m_currentNode, nextNode);
305+
m_currentNode = nextNode;
306+
307+
return false;
294308
}
295309
default:
296310
break;

libsolidity/analysis/ControlFlowRevertPruner.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include <libsolutil/Algorithms.h>
2222

23+
#include <range/v3/algorithm/remove.hpp>
24+
2325

2426
namespace solidity::frontend
2527
{
@@ -192,7 +194,11 @@ void ControlFlowRevertPruner::modifyFunctionFlows()
192194
// change anymore, we treat all "unknown" states as
193195
// "reverting", since they can only be caused by
194196
// recursion.
197+
for (CFGNode * node: _node->exits)
198+
ranges::remove(node->entries, _node);
199+
195200
_node->exits = {functionFlow.revert};
201+
functionFlow.revert->entries.push_back(_node);
196202
return;
197203
default:
198204
break;

test/libsolidity/smtCheckerTests/functions/function_call_does_not_clear_local_vars.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ contract C {
1010
// ====
1111
// SMTEngine: all
1212
// ----
13+
// Warning 5740: (122-136): Unreachable code.

test/libsolidity/syntaxTests/multiVariableDeclaration/multiSingleVariableDeclaration.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ contract C {
55
}
66
}
77
// ----
8+
// Warning 5740: (78-79): Unreachable code.

test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationSimple.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ contract C {
1010
function h() internal pure returns (bytes memory, string storage s) { s = s; }
1111
}
1212
// ----
13+
// Warning 5740: (111-115): Unreachable code.
1314
// Warning 6321: (250-262): Unnamed return variable can remain unassigned. Add an explicit return with value to all non-reverting code paths or name the variable.

test/libsolidity/syntaxTests/nameAndTypeResolution/001_name_references.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ contract test {
33
function f(uint256) public returns (uint out) { f(variable); test; out; }
44
}
55
// ----
6+
// Warning 5740: (103-112): Unreachable code.
67
// Warning 6133: (103-107): Statement has no effect.

test/libsolidity/syntaxTests/viewPureChecker/call_internal_functions_success.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ contract C {
55
function i() payable public { i(); h(); g(); f(); }
66
}
77
// ----
8+
// Warning 5740: (102-105): Unreachable code.
9+
// Warning 5740: (140-143): Unreachable code.
10+
// Warning 5740: (145-148): Unreachable code.
11+
// Warning 5740: (191-194): Unreachable code.
12+
// Warning 5740: (196-199): Unreachable code.
13+
// Warning 5740: (201-204): Unreachable code.

test/libsolidity/syntaxTests/viewPureChecker/view_pure_abi_encode.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ contract C {
77
}
88
}
99
// ----
10+
// Warning 5740: (142-237): Unreachable code.

0 commit comments

Comments
 (0)