Skip to content

Commit 937f6af

Browse files
ryanschneiders1na
authored andcommitted
eth/tracers/native: panic on memory read in prestateTracer (ethereum#27691)
Co-authored-by: Sina Mahmoodi <[email protected]>
1 parent 9d0f197 commit 937f6af

File tree

3 files changed

+67
-39
lines changed

3 files changed

+67
-39
lines changed

eth/tracers/internal/tracetest/calltrace_test.go

Lines changed: 59 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -302,13 +302,13 @@ func TestInternals(t *testing.T) {
302302
byte(vm.CALL),
303303
},
304304
tracer: mkTracer("callTracer", nil),
305-
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"}`,
305+
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"}`,
306306
},
307307
{
308308
name: "Stack depletion in LOG0",
309309
code: []byte{byte(vm.LOG3)},
310310
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
311-
want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0xc350","gasUsed":"0xc350","to":"0x00000000000000000000000000000000deadbeef","input":"0x","error":"stack underflow (0 \u003c=\u003e 5)","value":"0x0","type":"CALL"}`,
311+
want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x13880","to":"0x00000000000000000000000000000000deadbeef","input":"0x","error":"stack underflow (0 \u003c=\u003e 5)","value":"0x0","type":"CALL"}`,
312312
},
313313
{
314314
name: "Mem expansion in LOG0",
@@ -321,11 +321,11 @@ func TestInternals(t *testing.T) {
321321
byte(vm.LOG0),
322322
},
323323
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
324-
want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0xc350","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}],"value":"0x0","type":"CALL"}`,
324+
want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}],"value":"0x0","type":"CALL"}`,
325325
},
326326
{
327327
// Leads to OOM on the prestate tracer
328-
name: "Prestate-tracer - mem expansion in CREATE2",
328+
name: "Prestate-tracer - CREATE2 OOM",
329329
code: []byte{
330330
byte(vm.PUSH1), 0x1,
331331
byte(vm.PUSH1), 0x0,
@@ -339,41 +339,62 @@ func TestInternals(t *testing.T) {
339339
byte(vm.PUSH1), 0x0,
340340
byte(vm.LOG0),
341341
},
342-
tracer: mkTracer("prestateTracer", json.RawMessage(`{ "withLog": true }`)),
343-
want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52640350"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"}}`,
342+
tracer: mkTracer("prestateTracer", nil),
343+
want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52647880"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"}}`,
344+
},
345+
{
346+
// CREATE2 which requires padding memory by prestate tracer
347+
name: "Prestate-tracer - CREATE2 Memory padding",
348+
code: []byte{
349+
byte(vm.PUSH1), 0x1,
350+
byte(vm.PUSH1), 0x0,
351+
byte(vm.MSTORE),
352+
byte(vm.PUSH1), 0x1,
353+
byte(vm.PUSH1), 0xff,
354+
byte(vm.PUSH1), 0x1,
355+
byte(vm.PUSH1), 0x0,
356+
byte(vm.CREATE2),
357+
byte(vm.PUSH1), 0xff,
358+
byte(vm.PUSH1), 0x0,
359+
byte(vm.LOG0),
360+
},
361+
tracer: mkTracer("prestateTracer", nil),
362+
want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52647880"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600160ff60016000f560ff6000a0"},"0x91ff9a805d36f54e3e272e230f3e3f5c1b330804":{"balance":"0x0"}}`,
344363
},
345364
} {
346-
_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
347-
core.GenesisAlloc{
348-
to: core.GenesisAccount{
349-
Code: tc.code,
350-
},
351-
origin: core.GenesisAccount{
352-
Balance: big.NewInt(500000000000000),
353-
},
354-
}, false)
355-
evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer})
356-
msg := &core.Message{
357-
To: &to,
358-
From: origin,
359-
Value: big.NewInt(0),
360-
GasLimit: 50000,
361-
GasPrice: big.NewInt(0),
362-
GasFeeCap: big.NewInt(0),
363-
GasTipCap: big.NewInt(0),
364-
SkipAccountChecks: false,
365-
}
366-
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(msg.GasLimit))
367-
if _, err := st.TransitionDb(); err != nil {
368-
t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err)
369-
}
370-
// Retrieve the trace result and compare against the expected
371-
res, err := tc.tracer.GetResult()
372-
if err != nil {
373-
t.Fatalf("test %v: failed to retrieve trace result: %v", tc.name, err)
374-
}
375-
if string(res) != tc.want {
376-
t.Fatalf("test %v: trace mismatch\n have: %v\n want: %v\n", tc.name, string(res), tc.want)
377-
}
365+
t.Run(tc.name, func(t *testing.T) {
366+
_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
367+
core.GenesisAlloc{
368+
to: core.GenesisAccount{
369+
Code: tc.code,
370+
},
371+
origin: core.GenesisAccount{
372+
Balance: big.NewInt(500000000000000),
373+
},
374+
}, false)
375+
evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer})
376+
msg := &core.Message{
377+
To: &to,
378+
From: origin,
379+
Value: big.NewInt(0),
380+
GasLimit: 80000,
381+
GasPrice: big.NewInt(0),
382+
GasFeeCap: big.NewInt(0),
383+
GasTipCap: big.NewInt(0),
384+
SkipAccountChecks: false,
385+
}
386+
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(msg.GasLimit))
387+
if _, err := st.TransitionDb(); err != nil {
388+
t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err)
389+
}
390+
// Retrieve the trace result and compare against the expected
391+
res, err := tc.tracer.GetResult()
392+
if err != nil {
393+
t.Fatalf("test %v: failed to retrieve trace result: %v", tc.name, err)
394+
}
395+
if string(res) != tc.want {
396+
t.Errorf("test %v: trace mismatch\n have: %v\n want: %v\n", tc.name, string(res), tc.want)
397+
}
398+
})
378399
}
379400
}

eth/tracers/native/call.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/ethereum/go-ethereum/common/hexutil"
2828
"github.com/ethereum/go-ethereum/core/vm"
2929
"github.com/ethereum/go-ethereum/eth/tracers"
30+
"github.com/ethereum/go-ethereum/log"
3031
)
3132

3233
//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
183184
data, err := tracers.GetMemoryCopyPadded(scope.Memory, int64(mStart.Uint64()), int64(mSize.Uint64()))
184185
if err != nil {
185186
// mSize was unrealistically large
187+
log.Warn("failed to copy CREATE2 input", "err", err, "tracer", "callTracer", "offset", mStart, "size", mSize)
186188
return
187189
}
188190

eth/tracers/native/prestate.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/ethereum/go-ethereum/core/vm"
2828
"github.com/ethereum/go-ethereum/crypto"
2929
"github.com/ethereum/go-ethereum/eth/tracers"
30+
"github.com/ethereum/go-ethereum/log"
3031
)
3132

3233
//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,
165166
case stackLen >= 4 && op == vm.CREATE2:
166167
offset := stackData[stackLen-2]
167168
size := stackData[stackLen-3]
168-
init := scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64()))
169+
init, err := tracers.GetMemoryCopyPadded(scope.Memory, int64(offset.Uint64()), int64(size.Uint64()))
170+
if err != nil {
171+
log.Warn("failed to copy CREATE2 input", "err", err, "tracer", "prestateTracer", "offset", offset, "size", size)
172+
return
173+
}
169174
inithash := crypto.Keccak256(init)
170175
salt := stackData[stackLen-4]
171176
addr := crypto.CreateAddress2(caller, salt.Bytes32(), inithash)

0 commit comments

Comments
 (0)