Skip to content
Merged
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
20 changes: 20 additions & 0 deletions math/overflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,23 @@ func SubInt(a, b int) int {
log.Trace("SubInt underflow", "a", a, "b", b)
return builtinMath.MinInt64
}

// MulInt32 performs multiplication on int32 and logs an error if the multiplication overflows
func MulInt32(a, b int32) int32 {
res, err := MulInt32WithErr(a, b)
if err != nil {
log.Trace("MulInt32 overflow", "a", a, "b", b)
return builtinMath.MaxInt32
}

return res
}

// MulInt32WithErr performs multiplication on int32 and returns an error if the multiplication overflows
func MulInt32WithErr(a, b int32) (int32, error) {
wide := int64(a) * int64(b)
if wide > builtinMath.MaxInt32 || wide < builtinMath.MinInt32 {
return builtinMath.MaxInt32, ErrMultiplicationOverflow
}
return int32(wide), nil
}
5 changes: 5 additions & 0 deletions mock/context/runtimeContextMock.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ func (r *RuntimeContextMock) UseGasBoundedShouldFailExecution() bool {
return true
}

// AttributeExtraGasUsage mocked method
func (r *RuntimeContextMock) AttributeExtraGasUsage() bool {
return true
}

// FailExecution mocked method
func (r *RuntimeContextMock) FailExecution(_ error) {
}
Expand Down
5 changes: 5 additions & 0 deletions mock/context/runtimeContextWrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,11 @@ func (contextWrapper *RuntimeContextWrapper) UseGasBoundedShouldFailExecution()
return contextWrapper.runtimeContext.UseGasBoundedShouldFailExecution()
}

// AttributeExtraGasUsage calls corresponding xxxFunc function, that by default in turn calls the original method of the wrapped RuntimeContext
func (contextWrapper *RuntimeContextWrapper) AttributeExtraGasUsage() bool {
return contextWrapper.runtimeContext.AttributeExtraGasUsage()
}

// GetVMExecutor calls corresponding xxxFunc function, that by default in turn calls the original method of the wrapped RuntimeContext
func (contextWrapper *RuntimeContextWrapper) GetVMExecutor() executor.Executor {
return contextWrapper.GetVMExecutorFunc()
Expand Down
7 changes: 6 additions & 1 deletion vmhost/contexts/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func (context *runtimeContext) makeInstanceFromContractByteCode(contract []byte,
context.iTracker.SetCodeHash(codeHash)
}

if newCode {
if newCode || context.verifyCode {
err = context.VerifyContractCode()
if err != nil {
context.iTracker.ForceCleanInstance(true)
Expand Down Expand Up @@ -733,6 +733,11 @@ func (context *runtimeContext) UseGasBoundedShouldFailExecution() bool {
return context.host.EnableEpochsHandler().IsFlagEnabled(vmhost.UseGasBoundedShouldFailExecutionFlag)
}

// AttributeExtraGasUsage returns true when flag is activated
func (context *runtimeContext) AttributeExtraGasUsage() bool {
return context.host.EnableEpochsHandler().IsFlagEnabled(vmhost.AttributeExtraGasUsageFlag)
}

// GetPointsUsed returns the gas amount spent by the currently running Wasmer instance.
func (context *runtimeContext) GetPointsUsed() uint64 {
if check.IfNil(context.iTracker.Instance()) {
Expand Down
3 changes: 3 additions & 0 deletions vmhost/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@ const (
// FixGetBalanceFlag defines the flag that activates the fix for get balance from the Barnard release
FixGetBalanceFlag core.EnableEpochFlag = "FixGetBalanceFlag"

// AttributeExtraGasUsageFlag defines the flag that activates the extra gas usage for extra attributes
AttributeExtraGasUsageFlag core.EnableEpochFlag = "AttributeExtraGasUsageFlag"

// all new flags must be added to allFlags slice from hostCore/host
)
2 changes: 1 addition & 1 deletion vmhost/hostCore/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ func (host *vmHost) execute(input *vmcommon.ContractCallInput) error {
// Replace the current Wasmer instance of the Runtime with a new one; this
// assumes that the instance was preserved on the Runtime instance stack
// before calling executeSmartContractCall().
err = runtime.StartWasmerInstance(contract, metering.GetGasForExecution(), false)
err = runtime.StartWasmerInstance(contract, metering.GetGasForExecution(), input.AllowInitFunction)
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions vmhost/hostCore/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var allFlags = []core.EnableEpochFlag{
vmhost.ValidationOnGobDecodeFlag,
vmhost.BarnardOpcodesFlag,
vmhost.FixGetBalanceFlag,
vmhost.AttributeExtraGasUsageFlag,
}

// vmHost implements HostContext interface.
Expand Down
2 changes: 1 addition & 1 deletion vmhost/hosttest/execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ func TestExecution_ManagedBuffers(t *testing.T) {
test.CreateInstanceContract(test.ParentAddress).
WithCode(test.GetTestSCCode("managed-buffers", "../../"))).
WithInput(test.CreateTestContractCallInputBuilder().
WithGasProvided(100000).
WithGasProvided(1000000).
WithFunction(mBuffer[functionNumber]). // mBufferFromBigIntUnsignedTest
WithArguments([]byte{byte(numberOfReps)}).
Build()).
Expand Down
1 change: 1 addition & 0 deletions vmhost/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ type RuntimeContext interface {
GetPointsUsed() uint64
SetPointsUsed(gasPoints uint64)
UseGasBoundedShouldFailExecution() bool
AttributeExtraGasUsage() bool
CleanInstance()

AddError(err error, otherInfo ...string)
Expand Down
3 changes: 2 additions & 1 deletion vmhost/vmhooks/baseOps.go
Original file line number Diff line number Diff line change
Expand Up @@ -1016,9 +1016,10 @@ func (context *VMHooksImpl) MultiTransferESDTNFTExecute(
return 1
}

numArgsFromMemory := math.MulInt32(numTokenTransfers, parsers.ArgsPerTransfer)
transferArgs, _, err := context.getArgumentsFromMemory(
host,
numTokenTransfers*parsers.ArgsPerTransfer,
numArgsFromMemory,
tokenTransfersArgsLengthOffset,
tokenTransferDataOffset,
)
Expand Down
8 changes: 8 additions & 0 deletions vmhost/vmhooks/bigIntOps.go
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,8 @@ func (context *VMHooksImpl) BigIntEMod(destinationHandle, op1Handle, op2Handle i
dest.Mod(a, b) // Mod implements Euclidean division (unlike Go)
}

const maxSqrtLen = 8000

// BigIntSqrt VMHooks implementation.
// @autogenerate(VMHooks)
func (context *VMHooksImpl) BigIntSqrt(destinationHandle, opHandle int32) {
Expand Down Expand Up @@ -804,6 +806,12 @@ func (context *VMHooksImpl) BigIntSqrt(destinationHandle, opHandle int32) {
context.FailExecution(vmhost.ErrBadLowerBounds)
return
}

if context.GetRuntimeContext().AttributeExtraGasUsage() && a.BitLen() > maxSqrtLen {
context.FailExecution(vmhost.ErrBadUpperBounds)
return
}

dest.Sqrt(a)
}

Expand Down
14 changes: 14 additions & 0 deletions vmhost/vmhooks/manBufOps.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,13 @@ func (context *VMHooksImpl) MBufferFromBigIntUnsigned(mBufferHandle int32, bigIn
return 1
}

byteLen := (value.BitLen() + 7) / 8
err = chargeGasForExtraLength(byteLen, context.GetVMHost())
if err != nil {
context.FailExecution(err)
return -1
}

managedType.SetBytes(mBufferHandle, value.Bytes())

return 0
Expand All @@ -558,6 +565,13 @@ func (context *VMHooksImpl) MBufferFromBigIntSigned(mBufferHandle int32, bigIntH
return 1
}

byteLen := (value.BitLen() + 7) / 8
err = chargeGasForExtraLength(byteLen, context.GetVMHost())
if err != nil {
context.FailExecution(err)
return -1
}

managedType.SetBytes(mBufferHandle, twos.ToBytes(value))
return 0
}
Expand Down
24 changes: 24 additions & 0 deletions vmhost/vmhooks/managedei.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const (
)

const EGLDTokenName = "EGLD-000000" // TODO: maybe move to core?
const safeAttributeLength = 100

// ManagedSCAddress VMHooks implementation.
// @autogenerate(VMHooks)
Expand Down Expand Up @@ -1528,6 +1529,12 @@ func ManagedIsESDTPausedWithHost(host vmhost.VMHost, tokenIDHandle int32) int32
return -1
}

err = chargeGasForExtraLength(len(tokenID), host)
if err != nil {
FailExecution(host, err)
return -1
}

if blockchain.IsPaused(tokenID) {
return 1
}
Expand Down Expand Up @@ -1669,10 +1676,27 @@ func ManagedIsBuiltinFunctionWithHost(host vmhost.VMHost, functionNameHandle int
return -1
}

lenFuncName := len(mBuffFunctionName)
err = chargeGasForExtraLength(lenFuncName, host)
if err != nil {
FailExecution(host, err)
return -1
}

isBuiltinFunction := host.IsBuiltinFunctionName(string(mBuffFunctionName))
if isBuiltinFunction {
return 1
}

return 0
}

func chargeGasForExtraLength(lenAttribute int, host vmhost.VMHost) error {
if !host.Runtime().AttributeExtraGasUsage() || lenAttribute < safeAttributeLength {
return nil
}

metering := host.Metering()
gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(lenAttribute))
return metering.UseGasBounded(gasToUse)
}
2 changes: 1 addition & 1 deletion vmhost/vmhookstest/manBuffers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ func TestManBuffers_mBufferFromBigIntUnsigned(t *testing.T) {
test.CreateInstanceContract(test.ParentAddress).
WithCode(test.GetTestSCCode("managed-buffers", "../../"))).
WithInput(test.CreateTestContractCallInputBuilder().
WithGasProvided(100000).
WithGasProvided(1000000).
WithFunction("mBufferFromBigIntUnsignedTest").
WithArguments([]byte{byte(numberOfReps)}).
Build()).
Expand Down
Loading