Skip to content

Commit d10d967

Browse files
committed
yulRun: Fix unexpected return value for call* instructions and add tests
1 parent b8699e7 commit d10d967

9 files changed

+73
-5
lines changed

test/libyul/YulInterpreterTest.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ YulInterpreterTest::YulInterpreterTest(string const& _filename):
5151
{
5252
m_source = m_reader.source();
5353
m_expectation = m_reader.simpleExpectations();
54+
m_simulateExternalCallsToSelf = m_reader.boolSetting("simulateExternalCall", false);
5455
}
5556

5657
TestCase::TestResult YulInterpreterTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted)
@@ -98,8 +99,8 @@ string YulInterpreterTest::interpret()
9899
state,
99100
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}),
100101
*m_ast,
101-
/*disableExternalCalls=*/true,
102-
/*disableMemoryTracing=*/false
102+
/*disableExternalCalls=*/ !m_simulateExternalCallsToSelf,
103+
/*disableMemoryTracing=*/ false
103104
);
104105
}
105106
catch (InterpreterTerminatedGeneric const&)

test/libyul/YulInterpreterTest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class YulInterpreterTest: public solidity::frontend::test::EVMVersionRestrictedT
4747

4848
std::shared_ptr<Block> m_ast;
4949
std::shared_ptr<AsmAnalysisInfo> m_analysisInfo;
50+
bool m_simulateExternalCallsToSelf = false;
5051
};
5152

5253
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
mstore(0x40, 0x42)
3+
4+
if iszero(calldatasize()) {
5+
let x := call(gas(), address(), 0, 0x40, 0x20, 0x100, 0x20)
6+
sstore(0x64, calldataload(0))
7+
sstore(0x100, x)
8+
return(0x0, 0)
9+
}
10+
return(0x40, 0x20)
11+
}
12+
// ====
13+
// simulateExternalCall: true
14+
// ----
15+
// Trace:
16+
// CALL(153, 0x11111111, 0, 64, 32, 256, 32)
17+
// RETURN(0, 0)
18+
// Memory dump:
19+
// 40: 0000000000000000000000000000000000000000000000000000000000000042
20+
// 100: 0000000000000000000000000000000000000000000000000000000000000042
21+
// Storage dump:
22+
// 0000000000000000000000000000000000000000000000000000000000000100: 0000000000000000000000000000000000000000000000000000000000000001

test/libyul/yulInterpreterTests/external_call.yul renamed to test/libyul/yulInterpreterTests/external_call_unexecuted.yul

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
let x := call(gas(), 0x45, 0x5, 0, 0x20, 0x30, 0x20)
3-
sstore(100, x)
3+
sstore(0x64, x)
44
}
55
// ----
66
// Trace:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
let x := callcode(gas(), 0x45, 0x5, 0, 0x20, 0x30, 0x20)
3+
sstore(100, x)
4+
}
5+
// ----
6+
// Trace:
7+
// CALLCODE(153, 69, 5, 0, 32, 48, 32)
8+
// Memory dump:
9+
// Storage dump:
10+
// 0000000000000000000000000000000000000000000000000000000000000064: 0000000000000000000000000000000000000000000000000000000000000001
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
let x := delegatecall(gas(), 0x45, 0, 0x20, 0x30, 0x20)
3+
sstore(100, x)
4+
}
5+
// ----
6+
// Trace:
7+
// DELEGATECALL(153, 69, 0, 32, 48, 32)
8+
// Memory dump:
9+
// Storage dump:
10+
// 0000000000000000000000000000000000000000000000000000000000000064: 0000000000000000000000000000000000000000000000000000000000000001
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
let x := staticcall(gas(), 0x45, 0, 0x20, 0x30, 0x20)
3+
sstore(0x64, x)
4+
}
5+
// ====
6+
// EVMVersion: >=byzantium
7+
// ----
8+
// Trace:
9+
// STATICCALL(153, 69, 0, 32, 48, 32)
10+
// Memory dump:
11+
// Storage dump:
12+
// 0000000000000000000000000000000000000000000000000000000000000064: 0000000000000000000000000000000000000000000000000000000000000001

test/tools/yulInterpreter/EVMInstructionInterpreter.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,13 +329,24 @@ u256 EVMInstructionInterpreter::eval(
329329
accessMemory(arg[3], arg[4]);
330330
accessMemory(arg[5], arg[6]);
331331
logTrace(_instruction, arg);
332-
return arg[0] & 1;
332+
// Randomly fail based on the called address if it isn't a call to self.
333+
// Used for fuzzing.
334+
return (
335+
(arg[0] > 0) &&
336+
(arg[1] == util::h160::Arith(m_state.address) || (arg[1] & 1))
337+
) ? 1 : 0;
333338
case Instruction::DELEGATECALL:
334339
case Instruction::STATICCALL:
335340
accessMemory(arg[2], arg[3]);
336341
accessMemory(arg[4], arg[5]);
337342
logTrace(_instruction, arg);
338-
return 0;
343+
344+
// Randomly fail based on the called address if it isn't a call to self.
345+
// Used for fuzzing.
346+
return (
347+
(arg[0] > 0) &&
348+
(arg[1] == util::h160::Arith(m_state.address) || (arg[1] & 1))
349+
) ? 1 : 0;
339350
case Instruction::RETURN:
340351
{
341352
m_state.returndata = {};

test/tools/yulInterpreter/Interpreter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,5 +500,6 @@ void ExpressionEvaluator::runExternalCall(evmasm::Instruction _instruction)
500500
0,
501501
memOutSize.convert_to<size_t>()
502502
);
503+
m_state.returndata = newInterpreter->returnData();
503504
}
504505
}

0 commit comments

Comments
 (0)