eth/tracers: fix panics occurring for invalid params in js-tracers

This commit is contained in:
Martin Holst Swende 2020-02-03 10:10:01 +01:00
parent b09b9f55fc
commit ee9ef1fbc4
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
2 changed files with 17 additions and 15 deletions

View file

@ -93,6 +93,15 @@ type memoryWrapper struct {
// slice returns the requested range of memory as a byte slice. // slice returns the requested range of memory as a byte slice.
func (mw *memoryWrapper) slice(begin, end int64) []byte { func (mw *memoryWrapper) slice(begin, end int64) []byte {
if end == begin {
return []byte{}
}
if end < begin || begin < 0 {
// TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
// runtime goes belly up https://github.com/golang/go/issues/15639.
log.Warn("Tracer accessed out of bound memory", "offset", begin, "end", end)
return nil
}
if mw.memory.Len() < int(end) { if mw.memory.Len() < int(end) {
// TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
// runtime goes belly up https://github.com/golang/go/issues/15639. // runtime goes belly up https://github.com/golang/go/issues/15639.
@ -104,7 +113,7 @@ func (mw *memoryWrapper) slice(begin, end int64) []byte {
// getUint returns the 32 bytes at the specified address interpreted as a uint. // getUint returns the 32 bytes at the specified address interpreted as a uint.
func (mw *memoryWrapper) getUint(addr int64) *big.Int { func (mw *memoryWrapper) getUint(addr int64) *big.Int {
if mw.memory.Len() < int(addr)+32 { if mw.memory.Len() < int(addr)+32 || addr < 0 {
// TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
// runtime goes belly up https://github.com/golang/go/issues/15639. // runtime goes belly up https://github.com/golang/go/issues/15639.
log.Warn("Tracer accessed out of bound memory", "available", mw.memory.Len(), "offset", addr, "size", 32) log.Warn("Tracer accessed out of bound memory", "available", mw.memory.Len(), "offset", addr, "size", 32)
@ -147,7 +156,7 @@ type stackWrapper struct {
// peek returns the nth-from-the-top element of the stack. // peek returns the nth-from-the-top element of the stack.
func (sw *stackWrapper) peek(idx int) *big.Int { func (sw *stackWrapper) peek(idx int) *big.Int {
if len(sw.stack.Data()) <= idx { if len(sw.stack.Data()) <= idx || idx < 0 {
// TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
// runtime goes belly up https://github.com/golang/go/issues/15639. // runtime goes belly up https://github.com/golang/go/issues/15639.
log.Warn("Tracer accessed out of bound stack", "size", len(sw.stack.Data()), "index", idx) log.Warn("Tracer accessed out of bound stack", "size", len(sw.stack.Data()), "index", idx)

View file

@ -63,44 +63,37 @@ func runTrace(tracer *Tracer) (json.RawMessage, error) {
return tracer.GetResult() return tracer.GetResult()
} }
// TestRegressionPanicSlice tests that we don't panic on bad arguments to memory access
func TestRegressionPanicSlice(t *testing.T) { func TestRegressionPanicSlice(t *testing.T) {
tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.memory.slice(-1,-2)); }, fault: function() {}, result: function() { return this.depths; }}") tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.memory.slice(-1,-2)); }, fault: function() {}, result: function() { return this.depths; }}")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if _, err = runTrace(tracer); err != nil {
ret, err := runTrace(tracer)
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
t.Logf("Got result %s", string(ret))
} }
// TestRegressionPanicSlice tests that we don't panic on bad arguments to stack peeks
func TestRegressionPanicPeek(t *testing.T) { func TestRegressionPanicPeek(t *testing.T) {
tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.stack.peek(-1)); }, fault: function() {}, result: function() { return this.depths; }}") tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.stack.peek(-1)); }, fault: function() {}, result: function() { return this.depths; }}")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if _, err = runTrace(tracer); err != nil {
ret, err := runTrace(tracer)
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
t.Logf("Expected return value to be [0,1,2], got %s", string(ret))
} }
// TestRegressionPanicSlice tests that we don't panic on bad arguments to memory getUint
func TestRegressionPanicGetUint(t *testing.T) { func TestRegressionPanicGetUint(t *testing.T) {
tracer, err := New("{ depths: [], step: function(log, db) { this.depths.push(log.memory.getUint(-64));}, fault: function() {}, result: function() { return this.depths; }}") tracer, err := New("{ depths: [], step: function(log, db) { this.depths.push(log.memory.getUint(-64));}, fault: function() {}, result: function() { return this.depths; }}")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if _, err = runTrace(tracer); err != nil {
ret, err := runTrace(tracer)
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
t.Logf("Expected return value to be [0,1,2], got %s", string(ret))
} }
func TestTracing(t *testing.T) { func TestTracing(t *testing.T) {