Skip to content
Closed
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
6 changes: 6 additions & 0 deletions testcommon/instanceSmartContractCallerTest.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ func (template *InstanceCallTestTemplate) WithWasmerSIGSEGVPassthrough(passthrou
return template
}

// WithEnableEpochsHandler sets a pre-built blockchain hook for the VM to work with.
func (template *InstanceCallTestTemplate) WithEnableEpochsHandler(enableEpochHandler vmcommon.EnableEpochsHandler) *InstanceCallTestTemplate {
template.hostBuilder.WithEnableEpochsHandler(enableEpochHandler)
return template
}

// GetVMHost returns the inner VMHost
func (template *InstanceCallTestTemplate) GetVMHost() vmhost.VMHost {
return template.host
Expand Down
6 changes: 6 additions & 0 deletions testcommon/instanceSmartContractCreatorTest.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ func (template *InstanceCreatorTestTemplate) WithWasmerSIGSEGVPassthrough(passth
return template
}

// WithEnableEpochsHandler sets the enableEpochsHandler
func (template *InstanceCreatorTestTemplate) WithEnableEpochsHandler(enableEpochsHandler vmcommon.EnableEpochsHandler) *InstanceCreatorTestTemplate {
template.hostBuilder.WithEnableEpochsHandler(enableEpochsHandler)
return template
}

// WithAddress provides the address for a TestCreateTemplateConfig
func (template *InstanceCreatorTestTemplate) WithAddress(address []byte) *InstanceCreatorTestTemplate {
template.address = address
Expand Down
6 changes: 6 additions & 0 deletions testcommon/testHostBuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ func (thb *TestHostBuilder) WithBlockchainHook(blockchainHook vmcommon.Blockchai
return thb
}

// WithEnableEpochsHandler sets a pre-built blockchain hook for the VM to work with.
func (thb *TestHostBuilder) WithEnableEpochsHandler(enableEpochHandler vmcommon.EnableEpochsHandler) *TestHostBuilder {
thb.vmHostParameters.EnableEpochsHandler = enableEpochHandler
return thb
}

// WithBuiltinFunctions sets up builtin functions in the blockchain hook.
// Only works if the blockchain hook is of type worldmock.MockWorld.
func (thb *TestHostBuilder) WithBuiltinFunctions() *TestHostBuilder {
Expand Down
3 changes: 3 additions & 0 deletions vmhost/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ const (

// FixBackTransferOPCODE defines the flag that activates the fix for get back transfer opcode
FixBackTransferOPCODE core.EnableEpochFlag = "FixBackTransferOPCODEFlag"

// DoNotIgnoreGobDecodeErrorFlag defines the flag that activates the error return of gobDecode validate function
DoNotIgnoreGobDecodeErrorFlag core.EnableEpochFlag = "DoNotIgnoreGobDecodeErrorFlag"
)
40 changes: 35 additions & 5 deletions vmhost/vmhooks/manBufOps.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package vmhooks
import (
"bytes"
"math/big"
"strings"

"github.com/multiversx/mx-chain-vm-go/executor"
"github.com/multiversx/mx-chain-vm-go/math"
Expand Down Expand Up @@ -668,12 +669,17 @@ func (context *VMHooksImpl) MBufferToBigFloat(mBufferHandle, bigFloatHandle int3
bigFloat := new(big.Float)
err = bigFloat.GobDecode(managedBuffer)
if err != nil {
if enableEpochsHandler.IsFlagEnabled(vmhost.MaskInternalDependenciesErrorsFlag) {
err = vmhost.ErrBigFloatDecode
}
isMaskInternalErrorsEnabled := enableEpochsHandler.IsFlagEnabled(vmhost.MaskInternalDependenciesErrorsFlag)
if !enableEpochsHandler.IsFlagEnabled(vmhost.DoNotIgnoreGobDecodeErrorFlag) && isErrorFromFloatValidate0(err) {
logEEI.Warn("ignored gobDecode error on bigFloat")
} else {
if isMaskInternalErrorsEnabled {
err = vmhost.ErrBigFloatDecode
}

context.FailExecution(err)
return 1
context.FailExecution(err)
return 1
}
}
if bigFloat.IsInf() {
context.FailExecution(vmhost.ErrInfinityFloatOperation)
Expand All @@ -684,6 +690,30 @@ func (context *VMHooksImpl) MBufferToBigFloat(mBufferHandle, bigFloatHandle int3
return 0
}

// go1.22 brought in a new function to bigFloats GobDecode. It calls an extra validate0() function vs bigFloat implementations of before
// the fix to make this independent on the go compiler it is to ignore
func isErrorFromFloatValidate0(err error) bool {
errStr := err.Error()

if !strings.Contains(errStr, "Float.GobDecode: ") {
return false
}

if strings.Contains(errStr, "nonzero finite number with empty mantissa") {
return true
}

if strings.Contains(errStr, "msb not set") {
return true
}

if strings.Contains(errStr, "zero precision") {
return true
}

return false
}

// MBufferFromBigFloat VMHooks implementation.
// @autogenerate(VMHooks)
func (context *VMHooksImpl) MBufferFromBigFloat(mBufferHandle, bigFloatHandle int32) int32 {
Expand Down
33 changes: 33 additions & 0 deletions vmhost/vmhookstest/bigFloats_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package vmhookstest

import (
"github.com/multiversx/mx-chain-core-go/core"
"github.com/multiversx/mx-chain-scenario-go/worldmock"
"math"
"math/big"
"testing"
Expand Down Expand Up @@ -113,7 +115,38 @@
func TestBigFloats_Panic_FailExecution_Add(t *testing.T) {
floatArgument1 := []byte{1, 10, 0, 0, 0, 53, 0, 0, 0, 58, 0, 31, 28, 26, 150, 254, 14, 45}
floatArgument2 := []byte{1, 11, 0, 0, 0, 53, 0, 0, 0, 52, 222, 212, 49, 108, 64, 122, 107, 100}

test.BuildInstanceCallTest(t).
WithContracts(
test.CreateInstanceContract(test.ParentAddress).
WithCode(test.GetTestSCCode("big-floats", "../../"))).
WithInput(test.CreateTestContractCallInputBuilder().
WithGasProvided(100000).
WithFunction("BigFloatAddTest").
WithArguments([]byte{0, 0, 0, byte(10)},
floatArgument1, floatArgument2).
Build()).
AndAssertResults(func(host vmhost.VMHost, stubBlockchainHook *contextmock.BlockchainHookStub, verify *test.VMOutputVerifier) {
verify.
ReturnCode(10).
ReturnMessage("this big Float operation is not permitted while doing float.Add")
})
}

func TestBigFloats_Panic_FailExecution_AddIgnoreFlag(t *testing.T) {
floatArgument1 := []byte{1, 10, 0, 0, 0, 53, 0, 0, 0, 58, 0, 31, 28, 26, 150, 254, 14, 45}
floatArgument2 := []byte{1, 11, 0, 0, 0, 53, 0, 0, 0, 52, 222, 212, 49, 108, 64, 122, 107, 100}

enableEpochsHander := &worldmock.EnableEpochsHandlerStub{
IsFlagEnabledCalled: func(flag core.EnableEpochFlag) bool {
if flag == vmhost.DoNotIgnoreGobDecodeErrorFlag {

Check failure on line 142 in vmhost/vmhookstest/bigFloats_test.go

View workflow job for this annotation

GitHub Actions / golangci linter

S1008: should use 'return flag != vmhost.DoNotIgnoreGobDecodeErrorFlag' instead of 'if flag == vmhost.DoNotIgnoreGobDecodeErrorFlag { return false }; return true' (gosimple)
return false
}
return true
},
}
test.BuildInstanceCallTest(t).
WithEnableEpochsHandler(enableEpochsHander).
WithContracts(
test.CreateInstanceContract(test.ParentAddress).
WithCode(test.GetTestSCCode("big-floats", "../../"))).
Expand Down
Loading