Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion core/vm/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func (m *Memory) Free() {
// To reduce peak allocation, return only smaller memory instances to the pool.
const maxBufferSize = 16 << 10
if cap(m.store) <= maxBufferSize {
clear(m.store)
m.store = m.store[:0]
m.lastGasCost = 0
memoryPool.Put(m)
Expand Down Expand Up @@ -79,7 +80,11 @@ func (m *Memory) Set32(offset uint64, val *uint256.Int) {
// Resize resizes the memory to size
func (m *Memory) Resize(size uint64) {
if uint64(m.Len()) < size {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we always reuse the Memory instance without clearing.

// Free returns the memory to the pool.
func (m *Memory) Free() {
	// To reduce peak allocation, return only smaller memory instances to the pool.
	const maxBufferSize = 16 << 10
	if cap(m.store) <= maxBufferSize {
		m.store = m.store[:0]
		m.lastGasCost = 0
		memoryPool.Put(m)
	}
}

After the resize, the junks will also be visible, for instance:

  • T0; memory is empty (the underlying slice is 0x1,0x2)
  • T1; memory is resized to 2, the memory becomes [0x1, 0x2]
  • T2; the EVM only use the first byte somehow (not sure if it's possible), then the memory becomes [correct-data, junk]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

diff --git a/core/vm/memory.go b/core/vm/memory.go
index 5e11e83748..2e71c16c1a 100644
--- a/core/vm/memory.go
+++ b/core/vm/memory.go
@@ -44,6 +44,8 @@ func (m *Memory) Free() {
 	// To reduce peak allocation, return only smaller memory instances to the pool.
 	const maxBufferSize = 16 << 10
 	if cap(m.store) <= maxBufferSize {
+		clear(m.store) // zero out the bytes before truncating the length
+
 		m.store = m.store[:0]
 		m.lastGasCost = 0
 		memoryPool.Put(m)
@@ -79,7 +81,11 @@ func (m *Memory) Set32(offset uint64, val *uint256.Int) {
 // Resize resizes the memory to size
 func (m *Memory) Resize(size uint64) {
 	if uint64(m.Len()) < size {
-		m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
+		if uint64(cap(m.store)) > size {
+			m.store = m.store[:size]
+		} else {
+			m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
+		}
 	}
 }
 

m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
if uint64(cap(m.store)) > size {
m.store = m.store[:size]
} else {
m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions core/vm/memory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,10 @@ func TestMemoryCopy(t *testing.T) {
}
}
}

func BenchmarkResize(b *testing.B) {
memory := NewMemory()
for i := range b.N {
memory.Resize(uint64(i))
}
}
Loading