eth/tracers/native: panic on memory read in prestateTracer (#27691)
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
This commit is contained in:
parent
1e069cf802
commit
517ac886d4
@ -302,13 +302,13 @@ func TestInternals(t *testing.T) {
|
|||||||
byte(vm.CALL),
|
byte(vm.CALL),
|
||||||
},
|
},
|
||||||
tracer: mkTracer("callTracer", nil),
|
tracer: mkTracer("callTracer", nil),
|
||||||
want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0xc350","gasUsed":"0x54d8","to":"0x00000000000000000000000000000000deadbeef","input":"0x","calls":[{"from":"0x00000000000000000000000000000000deadbeef","gas":"0x6cbf","gasUsed":"0x0","to":"0x00000000000000000000000000000000000000ff","input":"0x","value":"0x0","type":"CALL"}],"value":"0x0","type":"CALL"}`,
|
want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x54d8","to":"0x00000000000000000000000000000000deadbeef","input":"0x","calls":[{"from":"0x00000000000000000000000000000000deadbeef","gas":"0xe01a","gasUsed":"0x0","to":"0x00000000000000000000000000000000000000ff","input":"0x","value":"0x0","type":"CALL"}],"value":"0x0","type":"CALL"}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Stack depletion in LOG0",
|
name: "Stack depletion in LOG0",
|
||||||
code: []byte{byte(vm.LOG3)},
|
code: []byte{byte(vm.LOG3)},
|
||||||
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
|
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
|
||||||
want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0xc350","gasUsed":"0xc350","to":"0x00000000000000000000000000000000deadbeef","input":"0x","error":"stack underflow (0 \u003c=\u003e 5)","value":"0x0","type":"CALL"}`,
|
want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x13880","to":"0x00000000000000000000000000000000deadbeef","input":"0x","error":"stack underflow (0 \u003c=\u003e 5)","value":"0x0","type":"CALL"}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Mem expansion in LOG0",
|
name: "Mem expansion in LOG0",
|
||||||
@ -321,11 +321,11 @@ func TestInternals(t *testing.T) {
|
|||||||
byte(vm.LOG0),
|
byte(vm.LOG0),
|
||||||
},
|
},
|
||||||
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
|
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
|
||||||
want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0xc350","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}],"value":"0x0","type":"CALL"}`,
|
want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}],"value":"0x0","type":"CALL"}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Leads to OOM on the prestate tracer
|
// Leads to OOM on the prestate tracer
|
||||||
name: "Prestate-tracer - mem expansion in CREATE2",
|
name: "Prestate-tracer - CREATE2 OOM",
|
||||||
code: []byte{
|
code: []byte{
|
||||||
byte(vm.PUSH1), 0x1,
|
byte(vm.PUSH1), 0x1,
|
||||||
byte(vm.PUSH1), 0x0,
|
byte(vm.PUSH1), 0x0,
|
||||||
@ -339,41 +339,62 @@ func TestInternals(t *testing.T) {
|
|||||||
byte(vm.PUSH1), 0x0,
|
byte(vm.PUSH1), 0x0,
|
||||||
byte(vm.LOG0),
|
byte(vm.LOG0),
|
||||||
},
|
},
|
||||||
tracer: mkTracer("prestateTracer", json.RawMessage(`{ "withLog": true }`)),
|
tracer: mkTracer("prestateTracer", nil),
|
||||||
want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52640350"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"}}`,
|
want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52647880"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"}}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// CREATE2 which requires padding memory by prestate tracer
|
||||||
|
name: "Prestate-tracer - CREATE2 Memory padding",
|
||||||
|
code: []byte{
|
||||||
|
byte(vm.PUSH1), 0x1,
|
||||||
|
byte(vm.PUSH1), 0x0,
|
||||||
|
byte(vm.MSTORE),
|
||||||
|
byte(vm.PUSH1), 0x1,
|
||||||
|
byte(vm.PUSH1), 0xff,
|
||||||
|
byte(vm.PUSH1), 0x1,
|
||||||
|
byte(vm.PUSH1), 0x0,
|
||||||
|
byte(vm.CREATE2),
|
||||||
|
byte(vm.PUSH1), 0xff,
|
||||||
|
byte(vm.PUSH1), 0x0,
|
||||||
|
byte(vm.LOG0),
|
||||||
|
},
|
||||||
|
tracer: mkTracer("prestateTracer", nil),
|
||||||
|
want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52647880"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600160ff60016000f560ff6000a0"},"0x91ff9a805d36f54e3e272e230f3e3f5c1b330804":{"balance":"0x0"}}`,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
core.GenesisAlloc{
|
_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
|
||||||
to: core.GenesisAccount{
|
core.GenesisAlloc{
|
||||||
Code: tc.code,
|
to: core.GenesisAccount{
|
||||||
},
|
Code: tc.code,
|
||||||
origin: core.GenesisAccount{
|
},
|
||||||
Balance: big.NewInt(500000000000000),
|
origin: core.GenesisAccount{
|
||||||
},
|
Balance: big.NewInt(500000000000000),
|
||||||
}, false)
|
},
|
||||||
evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer})
|
}, false)
|
||||||
msg := &core.Message{
|
evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer})
|
||||||
To: &to,
|
msg := &core.Message{
|
||||||
From: origin,
|
To: &to,
|
||||||
Value: big.NewInt(0),
|
From: origin,
|
||||||
GasLimit: 50000,
|
Value: big.NewInt(0),
|
||||||
GasPrice: big.NewInt(0),
|
GasLimit: 80000,
|
||||||
GasFeeCap: big.NewInt(0),
|
GasPrice: big.NewInt(0),
|
||||||
GasTipCap: big.NewInt(0),
|
GasFeeCap: big.NewInt(0),
|
||||||
SkipAccountChecks: false,
|
GasTipCap: big.NewInt(0),
|
||||||
}
|
SkipAccountChecks: false,
|
||||||
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
}
|
||||||
if _, err := st.TransitionDb(); err != nil {
|
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
||||||
t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err)
|
if _, err := st.TransitionDb(); err != nil {
|
||||||
}
|
t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err)
|
||||||
// Retrieve the trace result and compare against the expected
|
}
|
||||||
res, err := tc.tracer.GetResult()
|
// Retrieve the trace result and compare against the expected
|
||||||
if err != nil {
|
res, err := tc.tracer.GetResult()
|
||||||
t.Fatalf("test %v: failed to retrieve trace result: %v", tc.name, err)
|
if err != nil {
|
||||||
}
|
t.Fatalf("test %v: failed to retrieve trace result: %v", tc.name, err)
|
||||||
if string(res) != tc.want {
|
}
|
||||||
t.Fatalf("test %v: trace mismatch\n have: %v\n want: %v\n", tc.name, string(res), tc.want)
|
if string(res) != tc.want {
|
||||||
}
|
t.Errorf("test %v: trace mismatch\n have: %v\n want: %v\n", tc.name, string(res), tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type callFrame -field-override callFrameMarshaling -out gen_callframe_json.go
|
//go:generate go run github.com/fjl/gencodec -type callFrame -field-override callFrameMarshaling -out gen_callframe_json.go
|
||||||
@ -183,6 +184,7 @@ func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, sco
|
|||||||
data, err := tracers.GetMemoryCopyPadded(scope.Memory, int64(mStart.Uint64()), int64(mSize.Uint64()))
|
data, err := tracers.GetMemoryCopyPadded(scope.Memory, int64(mStart.Uint64()), int64(mSize.Uint64()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// mSize was unrealistically large
|
// mSize was unrealistically large
|
||||||
|
log.Warn("failed to copy CREATE2 input", "err", err, "tracer", "callTracer", "offset", mStart, "size", mSize)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type account -field-override accountMarshaling -out gen_account_json.go
|
//go:generate go run github.com/fjl/gencodec -type account -field-override accountMarshaling -out gen_account_json.go
|
||||||
@ -165,7 +166,11 @@ func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64,
|
|||||||
case stackLen >= 4 && op == vm.CREATE2:
|
case stackLen >= 4 && op == vm.CREATE2:
|
||||||
offset := stackData[stackLen-2]
|
offset := stackData[stackLen-2]
|
||||||
size := stackData[stackLen-3]
|
size := stackData[stackLen-3]
|
||||||
init := scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64()))
|
init, err := tracers.GetMemoryCopyPadded(scope.Memory, int64(offset.Uint64()), int64(size.Uint64()))
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("failed to copy CREATE2 input", "err", err, "tracer", "prestateTracer", "offset", offset, "size", size)
|
||||||
|
return
|
||||||
|
}
|
||||||
inithash := crypto.Keccak256(init)
|
inithash := crypto.Keccak256(init)
|
||||||
salt := stackData[stackLen-4]
|
salt := stackData[stackLen-4]
|
||||||
addr := crypto.CreateAddress2(caller, salt.Bytes32(), inithash)
|
addr := crypto.CreateAddress2(caller, salt.Bytes32(), inithash)
|
||||||
|
Loading…
Reference in New Issue
Block a user