From ae8d4d4629682571e58c1f8c8d5d8589cdecd30d Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Thu, 7 Aug 2025 20:10:03 +0900 Subject: [PATCH 1/2] core/vm: fix 7823 in case of base length == 0 and mod length == 0. Augment size cap check to catch case where base/exp/mod len > 2**64 (although this is unlikely to happen in practice) --- core/vm/contracts.go | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 21307ff5ace..4a71342e9e7 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -500,23 +500,31 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { func (c *bigModExp) Run(input []byte) ([]byte, error) { var ( - baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() - expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() - modLen = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64() + baseLenBig = new(big.Int).SetBytes(getData(input, 0, 32)) + expLenBig = new(big.Int).SetBytes(getData(input, 32, 32)) + modLenBig = new(big.Int).SetBytes(getData(input, 64, 32)) + baseLen = baseLenBig.Uint64() + expLen = expLenBig.Uint64() + modLen = modLenBig.Uint64() ) if len(input) > 96 { input = input[96:] } else { input = input[:0] } + + inputLensHighBitsSet := baseLenBig.Rsh(baseLenBig, 64).Cmp(common.Big0) != 0 || + expLenBig.Rsh(expLenBig, 64).Cmp(common.Big0) != 0 || + modLenBig.Rsh(modLenBig, 64).Cmp(common.Big0) != 0 + + // enforce size cap for inputs + if c.eip7823 && (max(baseLen, expLen, modLen) > 1024 || inputLensHighBitsSet) { + return nil, errors.New("one or more of base/exponent/modulus length exceeded 1024 bytes") + } // Handle a special case when both the base and mod length is zero if baseLen == 0 && modLen == 0 { return []byte{}, nil } - // enforce size cap for inputs - if c.eip7823 && max(baseLen, expLen, modLen) > 1024 { - return nil, errors.New("one or more of base/exponent/modulus length exceeded 1024 bytes") - } // Retrieve the operands and execute the exponentiation var ( base = new(big.Int).SetBytes(getData(input, 0, baseLen)) From c8d18bf9c39263552c24dd181369a2281b442a03 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 15 Aug 2025 15:41:46 +0200 Subject: [PATCH 2/2] core/vm: remove shift --- core/vm/contracts.go | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 4a71342e9e7..2443aaae8eb 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -500,12 +500,13 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { func (c *bigModExp) Run(input []byte) ([]byte, error) { var ( - baseLenBig = new(big.Int).SetBytes(getData(input, 0, 32)) - expLenBig = new(big.Int).SetBytes(getData(input, 32, 32)) - modLenBig = new(big.Int).SetBytes(getData(input, 64, 32)) - baseLen = baseLenBig.Uint64() - expLen = expLenBig.Uint64() - modLen = modLenBig.Uint64() + baseLenBig = new(big.Int).SetBytes(getData(input, 0, 32)) + expLenBig = new(big.Int).SetBytes(getData(input, 32, 32)) + modLenBig = new(big.Int).SetBytes(getData(input, 64, 32)) + baseLen = baseLenBig.Uint64() + expLen = expLenBig.Uint64() + modLen = modLenBig.Uint64() + inputLenOverflow = max(baseLenBig.BitLen(), expLenBig.BitLen(), modLenBig.BitLen()) > 64 ) if len(input) > 96 { input = input[96:] @@ -513,12 +514,8 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) { input = input[:0] } - inputLensHighBitsSet := baseLenBig.Rsh(baseLenBig, 64).Cmp(common.Big0) != 0 || - expLenBig.Rsh(expLenBig, 64).Cmp(common.Big0) != 0 || - modLenBig.Rsh(modLenBig, 64).Cmp(common.Big0) != 0 - // enforce size cap for inputs - if c.eip7823 && (max(baseLen, expLen, modLen) > 1024 || inputLensHighBitsSet) { + if c.eip7823 && (inputLenOverflow || max(baseLen, expLen, modLen) > 1024) { return nil, errors.New("one or more of base/exponent/modulus length exceeded 1024 bytes") } // Handle a special case when both the base and mod length is zero