Merge pull request #19348 from LiangMa/overflowPR

core/vm: Correct the Memory Gas Overflow condition
This commit is contained in:
Péter Szilágyi 2019-04-01 17:12:13 +03:00 committed by GitHub
commit 92faf1bf7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 22 deletions

View File

@ -25,21 +25,17 @@ import (
// memoryGasCost calculates the quadratic gas for memory expansion. It does so // memoryGasCost calculates the quadratic gas for memory expansion. It does so
// only for the memory region that is expanded, not the total memory. // only for the memory region that is expanded, not the total memory.
func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
if newMemSize == 0 { if newMemSize == 0 {
return 0, nil return 0, nil
} }
// The maximum that will fit in a uint64 is max_word_count - 1 // The maximum that will fit in a uint64 is max_word_count - 1. Anything above
// anything above that will result in an overflow. // that will result in an overflow. Additionally, a newMemSize which results in
// Additionally, a newMemSize which results in a // a newMemSizeWords larger than 0xFFFFFFFF will cause the square operation to
// newMemSizeWords larger than 0x7ffffffff will cause the square operation // overflow. The constant 0x1FFFFFFFE0 is the highest number that can be used
// to overflow. // without overflowing the gas calculation.
// The constant 0xffffffffe0 is the highest number that can be used without if newMemSize > 0x1FFFFFFFE0 {
// overflowing the gas calculation
if newMemSize > 0xffffffffe0 {
return 0, errGasUintOverflow return 0, errGasUintOverflow
} }
newMemSizeWords := toWordSize(newMemSize) newMemSizeWords := toWordSize(newMemSize)
newMemSize = newMemSizeWords * 32 newMemSize = newMemSizeWords * 32

View File

@ -19,18 +19,21 @@ package vm
import "testing" import "testing"
func TestMemoryGasCost(t *testing.T) { func TestMemoryGasCost(t *testing.T) {
//size := uint64(math.MaxUint64 - 64) tests := []struct {
size := uint64(0xffffffffe0) size uint64
v, err := memoryGasCost(&Memory{}, size) cost uint64
if err != nil { overflow bool
t.Error("didn't expect error:", err) }{
{0x1fffffffe0, 36028809887088637, false},
{0x1fffffffe1, 0, true},
} }
if v != 36028899963961341 { for i, tt := range tests {
t.Errorf("Expected: 36028899963961341, got %d", v) v, err := memoryGasCost(&Memory{}, tt.size)
if (err == errGasUintOverflow) != tt.overflow {
t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == errGasUintOverflow, tt.overflow)
}
if v != tt.cost {
t.Errorf("test %d: gas cost mismatch: have %v, want %v", i, v, tt.cost)
} }
_, err = memoryGasCost(&Memory{}, size+1)
if err == nil {
t.Error("expected error")
} }
} }