mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
core/vm: updated to v1.0.6, fix bugs
This commit is contained in:
parent
e61f11a7a3
commit
a484bfacf0
7 changed files with 131 additions and 45 deletions
|
|
@ -206,7 +206,7 @@ func parseAndValidate(s string, isInitCode bool) (*vm.Container, error) {
|
||||||
if err := c.UnmarshalBinary(b, isInitCode); err != nil {
|
if err := c.UnmarshalBinary(b, isInitCode); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := c.ValidateCode(&jt); err != nil {
|
if err := c.ValidateCode(&jt, isInitCode); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &c, nil
|
return &c, nil
|
||||||
|
|
|
||||||
|
|
@ -300,7 +300,7 @@ func applyEOFChecks(prestate *Prestate, chainConfig *params.ChainConfig) error {
|
||||||
err = c.UnmarshalBinary(acc.Code, false)
|
err = c.UnmarshalBinary(acc.Code, false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
jt := vm.NewPragueEOFInstructionSetForTesting()
|
jt := vm.NewPragueEOFInstructionSetForTesting()
|
||||||
err = c.ValidateCode(&jt)
|
err = c.ValidateCode(&jt, false)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NewError(ErrorConfig, fmt.Errorf("code at %s considered invalid: %v", addr, err))
|
return NewError(ErrorConfig, fmt.Errorf("code at %s considered invalid: %v", addr, err))
|
||||||
|
|
|
||||||
|
|
@ -1005,7 +1005,7 @@ func opReturnContract(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
|
||||||
if err := c.UnmarshalBinary(deployedCode, true); err != nil {
|
if err := c.UnmarshalBinary(deployedCode, true); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := c.ValidateCode(interpreter.tableEOF); err != nil {
|
if err := c.ValidateCode(interpreter.tableEOF, true); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(c.Data) < c.DataSize {
|
if len(c.Data) < c.DataSize {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -143,12 +145,19 @@ func (c *Container) MarshalBinary() []byte {
|
||||||
|
|
||||||
// UnmarshalBinary decodes an EOF container.
|
// UnmarshalBinary decodes an EOF container.
|
||||||
func (c *Container) UnmarshalBinary(b []byte, isInitcode bool) error {
|
func (c *Container) UnmarshalBinary(b []byte, isInitcode bool) error {
|
||||||
|
return c.unmarshaSubContainer(b, isInitcode, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) unmarshaSubContainer(b []byte, isInitcode bool, topLevel bool) error {
|
||||||
if !hasEOFMagic(b) {
|
if !hasEOFMagic(b) {
|
||||||
return fmt.Errorf("%w: want %x", ErrInvalidMagic, eofMagic)
|
return fmt.Errorf("%w: want %x", ErrInvalidMagic, eofMagic)
|
||||||
}
|
}
|
||||||
if len(b) < 14 {
|
if len(b) < 14 {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
|
if len(b) > params.MaxInitCodeSize {
|
||||||
|
return ErrMaxInitCodeSizeExceeded
|
||||||
|
}
|
||||||
if !isEOFVersion1(b) {
|
if !isEOFVersion1(b) {
|
||||||
return fmt.Errorf("%w: have %d, want %d", ErrInvalidVersion, b[2], eof1Version)
|
return fmt.Errorf("%w: have %d, want %d", ErrInvalidVersion, b[2], eof1Version)
|
||||||
}
|
}
|
||||||
|
|
@ -282,7 +291,7 @@ func (c *Container) UnmarshalBinary(b []byte, isInitcode bool) error {
|
||||||
}
|
}
|
||||||
c := new(Container)
|
c := new(Container)
|
||||||
end := min(idx+size, len(b))
|
end := min(idx+size, len(b))
|
||||||
if err := c.UnmarshalBinary(b[idx:end], isInitcode); err != nil {
|
if err := c.unmarshaSubContainer(b[idx:end], isInitcode, false); err != nil {
|
||||||
return fmt.Errorf("%w for section %d", err, i)
|
return fmt.Errorf("%w for section %d", err, i)
|
||||||
}
|
}
|
||||||
container = append(container, c)
|
container = append(container, c)
|
||||||
|
|
@ -299,6 +308,9 @@ func (c *Container) UnmarshalBinary(b []byte, isInitcode bool) error {
|
||||||
if !isInitcode {
|
if !isInitcode {
|
||||||
end = min(idx+dataSize, len(b))
|
end = min(idx+dataSize, len(b))
|
||||||
}
|
}
|
||||||
|
if topLevel && len(b) != idx+dataSize {
|
||||||
|
return ErrTruncatedTopLevelContainer
|
||||||
|
}
|
||||||
c.Data = b[idx:end]
|
c.Data = b[idx:end]
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -306,8 +318,13 @@ func (c *Container) UnmarshalBinary(b []byte, isInitcode bool) error {
|
||||||
|
|
||||||
// ValidateCode validates each code section of the container against the EOF v1
|
// ValidateCode validates each code section of the container against the EOF v1
|
||||||
// rule set.
|
// rule set.
|
||||||
func (c *Container) ValidateCode(jt *JumpTable) error {
|
func (c *Container) ValidateCode(jt *JumpTable, isInitCode bool) error {
|
||||||
|
return c.validateSubContainer(jt, isInitCode, NotRefByEither)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) validateSubContainer(jt *JumpTable, isInitCode bool, refBy int) error {
|
||||||
visited := make(map[int]struct{})
|
visited := make(map[int]struct{})
|
||||||
|
subContainerVisited := make(map[int]int)
|
||||||
toVisit := []int{0}
|
toVisit := []int{0}
|
||||||
for len(toVisit) > 0 {
|
for len(toVisit) > 0 {
|
||||||
// TODO check if this can be used as a DOS
|
// TODO check if this can be used as a DOS
|
||||||
|
|
@ -321,17 +338,31 @@ func (c *Container) ValidateCode(jt *JumpTable) error {
|
||||||
code = c.Code[index]
|
code = c.Code[index]
|
||||||
)
|
)
|
||||||
if _, ok := visited[index]; !ok {
|
if _, ok := visited[index]; !ok {
|
||||||
v, err := validateCode(code, index, c, jt)
|
res, err := validateCode(code, index, c, jt, isInitCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
visited[index] = struct{}{}
|
visited[index] = struct{}{}
|
||||||
// Mark all sections that can be visited from here.
|
// Mark all sections that can be visited from here.
|
||||||
for idx := range v {
|
for idx := range res.VisitedCode {
|
||||||
if _, ok := visited[idx]; !ok {
|
if _, ok := visited[idx]; !ok {
|
||||||
toVisit = append(toVisit, idx)
|
toVisit = append(toVisit, idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Mark all subcontainer that can be visited from here.
|
||||||
|
for idx, reference := range res.VisitedSubContainers {
|
||||||
|
// Make sure subcontainers are only ever referenced by either EOFCreate or ReturnContract
|
||||||
|
if ref, ok := subContainerVisited[idx]; ok && ref != reference {
|
||||||
|
return errors.New("section referenced by both EOFCreate and ReturnContract")
|
||||||
|
}
|
||||||
|
subContainerVisited[idx] = reference
|
||||||
|
}
|
||||||
|
if refBy == RefByReturnContract && res.IsInitCode {
|
||||||
|
return ErrIncompatibleContainerKind
|
||||||
|
}
|
||||||
|
if refBy == RefByEOFCreate && res.IsRuntime {
|
||||||
|
return ErrIncompatibleContainerKind
|
||||||
|
}
|
||||||
}
|
}
|
||||||
toVisit = toVisit[1:]
|
toVisit = toVisit[1:]
|
||||||
}
|
}
|
||||||
|
|
@ -339,8 +370,12 @@ func (c *Container) ValidateCode(jt *JumpTable) error {
|
||||||
if len(visited) != len(c.Code) {
|
if len(visited) != len(c.Code) {
|
||||||
return ErrUnreachableCode
|
return ErrUnreachableCode
|
||||||
}
|
}
|
||||||
for _, container := range c.ContainerSections {
|
for idx, container := range c.ContainerSections {
|
||||||
if err := container.ValidateCode(jt); err != nil {
|
reference, ok := subContainerVisited[idx]
|
||||||
|
if !ok {
|
||||||
|
return ErrOrphanedSubcontainer
|
||||||
|
}
|
||||||
|
if err := container.validateSubContainer(jt, isInitCode, reference); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -493,7 +493,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
||||||
if err := c.UnmarshalBinary(codeAndHash.code, isInitcodeEOF); err != nil {
|
if err := c.UnmarshalBinary(codeAndHash.code, isInitcodeEOF); err != nil {
|
||||||
return nil, common.Address{}, gas, fmt.Errorf("%w: %v", ErrInvalidEOFInitcode, err)
|
return nil, common.Address{}, gas, fmt.Errorf("%w: %v", ErrInvalidEOFInitcode, err)
|
||||||
}
|
}
|
||||||
if err := c.ValidateCode(evm.interpreter.tableEOF); err != nil {
|
if err := c.ValidateCode(evm.interpreter.tableEOF, isInitcodeEOF); err != nil {
|
||||||
return nil, common.Address{}, gas, fmt.Errorf("%w: %v", ErrInvalidEOFInitcode, err)
|
return nil, common.Address{}, gas, fmt.Errorf("%w: %v", ErrInvalidEOFInitcode, err)
|
||||||
}
|
}
|
||||||
contract.Container = &c
|
contract.Container = &c
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,29 @@ var (
|
||||||
ErrInvalidMaxStackHeight = errors.New("invalid max stack height")
|
ErrInvalidMaxStackHeight = errors.New("invalid max stack height")
|
||||||
ErrInvalidCodeTermination = errors.New("invalid code termination")
|
ErrInvalidCodeTermination = errors.New("invalid code termination")
|
||||||
ErrEOFCreateWithTruncatedSection = errors.New("eofcreate with truncated section")
|
ErrEOFCreateWithTruncatedSection = errors.New("eofcreate with truncated section")
|
||||||
|
ErrOrphanedSubcontainer = errors.New("subcontainer not referenced at all")
|
||||||
|
ErrIncompatibleContainerKind = errors.New("incompatible container kind")
|
||||||
|
ErrStopAndReturnContract = errors.New("Stop/Return and Returncontract in the same code section")
|
||||||
|
ErrStopInInitCode = errors.New("initcode contains a RETURN or STOP opcode")
|
||||||
|
ErrTruncatedTopLevelContainer = errors.New("truncated top level container")
|
||||||
ErrUnreachableCode = errors.New("unreachable code")
|
ErrUnreachableCode = errors.New("unreachable code")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NotRefByEither = iota
|
||||||
|
RefByReturnContract
|
||||||
|
RefByEOFCreate
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValidationResult struct {
|
||||||
|
VisitedCode map[int]struct{}
|
||||||
|
VisitedSubContainers map[int]int
|
||||||
|
IsInitCode bool
|
||||||
|
IsRuntime bool
|
||||||
|
}
|
||||||
|
|
||||||
// validateCode validates the code parameter against the EOF v1 validity requirements.
|
// validateCode validates the code parameter against the EOF v1 validity requirements.
|
||||||
func validateCode(code []byte, section int, container *Container, jt *JumpTable) (map[int]struct{}, error) {
|
func validateCode(code []byte, section int, container *Container, jt *JumpTable, isInitCode bool) (*ValidationResult, error) {
|
||||||
var (
|
var (
|
||||||
i = 0
|
i = 0
|
||||||
// Tracks the number of actual instructions in the code (e.g.
|
// Tracks the number of actual instructions in the code (e.g.
|
||||||
|
|
@ -49,7 +67,10 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable)
|
||||||
count = 0
|
count = 0
|
||||||
op OpCode
|
op OpCode
|
||||||
analysis bitvec
|
analysis bitvec
|
||||||
visited = make(map[int]struct{})
|
visitedCode = make(map[int]struct{})
|
||||||
|
visitedSubcontainers = make(map[int]int)
|
||||||
|
hasReturnContract bool
|
||||||
|
hasStop bool
|
||||||
)
|
)
|
||||||
// This loop visits every single instruction and verifies:
|
// This loop visits every single instruction and verifies:
|
||||||
// * if the instruction is valid for the given jump table.
|
// * if the instruction is valid for the given jump table.
|
||||||
|
|
@ -61,63 +82,88 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable)
|
||||||
count++
|
count++
|
||||||
op = OpCode(code[i])
|
op = OpCode(code[i])
|
||||||
if jt[op].undefined {
|
if jt[op].undefined {
|
||||||
return visited, fmt.Errorf("%w: op %s, pos %d", ErrUndefinedInstruction, op, i)
|
return nil, fmt.Errorf("%w: op %s, pos %d", ErrUndefinedInstruction, op, i)
|
||||||
}
|
}
|
||||||
if size := jt[op].immediate; size != 0 {
|
if size := jt[op].immediate; size != 0 {
|
||||||
if len(code) <= i+size {
|
if len(code) <= i+size {
|
||||||
return visited, fmt.Errorf("%w: op %s, pos %d", ErrTruncatedImmediate, op, i)
|
return nil, fmt.Errorf("%w: op %s, pos %d", ErrTruncatedImmediate, op, i)
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case op == RJUMP || op == RJUMPI:
|
case op == RJUMP || op == RJUMPI:
|
||||||
if err := checkDest(code, &analysis, i+1, i+3, len(code)); err != nil {
|
if err := checkDest(code, &analysis, i+1, i+3, len(code)); err != nil {
|
||||||
return visited, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case op == RJUMPV:
|
case op == RJUMPV:
|
||||||
max_size := int(code[i+1])
|
max_size := int(code[i+1])
|
||||||
length := max_size + 1
|
length := max_size + 1
|
||||||
if len(code) <= i+length {
|
if len(code) <= i+length {
|
||||||
return visited, fmt.Errorf("%w: jump table truncated, op %s, pos %d", ErrTruncatedImmediate, op, i)
|
return nil, fmt.Errorf("%w: jump table truncated, op %s, pos %d", ErrTruncatedImmediate, op, i)
|
||||||
}
|
}
|
||||||
offset := i + 2
|
offset := i + 2
|
||||||
for j := 0; j < length; j++ {
|
for j := 0; j < length; j++ {
|
||||||
if err := checkDest(code, &analysis, offset+j*2, offset+(length*2), len(code)); err != nil {
|
if err := checkDest(code, &analysis, offset+j*2, offset+(length*2), len(code)); err != nil {
|
||||||
return visited, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i += 2 * max_size
|
i += 2 * max_size
|
||||||
case op == CALLF:
|
case op == CALLF:
|
||||||
arg, _ := parseUint16(code[i+1:])
|
arg, _ := parseUint16(code[i+1:])
|
||||||
if arg >= len(container.Types) {
|
if arg >= len(container.Types) {
|
||||||
return visited, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrInvalidSectionArgument, arg, len(container.Types), i)
|
return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrInvalidSectionArgument, arg, len(container.Types), i)
|
||||||
}
|
}
|
||||||
if container.Types[arg].Output == 0x80 {
|
if container.Types[arg].Output == 0x80 {
|
||||||
return visited, fmt.Errorf("%w: section %v", ErrInvalidCallArgument, arg)
|
return nil, fmt.Errorf("%w: section %v", ErrInvalidCallArgument, arg)
|
||||||
}
|
}
|
||||||
visited[arg] = struct{}{}
|
visitedCode[arg] = struct{}{}
|
||||||
case op == JUMPF:
|
case op == JUMPF:
|
||||||
arg, _ := parseUint16(code[i+1:])
|
arg, _ := parseUint16(code[i+1:])
|
||||||
if arg >= len(container.Types) {
|
if arg >= len(container.Types) {
|
||||||
return visited, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrInvalidSectionArgument, arg, len(container.Types), i)
|
return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrInvalidSectionArgument, arg, len(container.Types), i)
|
||||||
}
|
}
|
||||||
visited[arg] = struct{}{}
|
visitedCode[arg] = struct{}{}
|
||||||
case op == DATALOADN:
|
case op == DATALOADN:
|
||||||
arg, _ := parseUint16(code[i+1:])
|
arg, _ := parseUint16(code[i+1:])
|
||||||
if arg+32 > len(container.Data) {
|
if arg+32 > len(container.Data) {
|
||||||
return visited, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrInvalidDataloadNArgument, arg, len(container.Data), i)
|
return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrInvalidDataloadNArgument, arg, len(container.Data), i)
|
||||||
}
|
}
|
||||||
case op == RETURNCONTRACT:
|
case op == RETURNCONTRACT:
|
||||||
arg := int(code[i+1])
|
arg := int(code[i+1])
|
||||||
if arg >= len(container.ContainerSections) {
|
if arg >= len(container.ContainerSections) {
|
||||||
return visited, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrUnreachableCode, arg, len(container.ContainerSections), i)
|
return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrUnreachableCode, arg, len(container.ContainerSections), i)
|
||||||
}
|
}
|
||||||
|
// We need to store per subcontainer how it was referenced
|
||||||
|
if v, ok := visitedSubcontainers[arg]; ok && v != RefByReturnContract {
|
||||||
|
return nil, fmt.Errorf("section already referenced, arg :%d", arg)
|
||||||
|
}
|
||||||
|
if hasStop {
|
||||||
|
return nil, ErrStopAndReturnContract
|
||||||
|
}
|
||||||
|
hasReturnContract = true
|
||||||
|
visitedSubcontainers[arg] = RefByReturnContract
|
||||||
case op == EOFCREATE:
|
case op == EOFCREATE:
|
||||||
arg := int(code[i+1])
|
arg := int(code[i+1])
|
||||||
if arg >= len(container.ContainerSections) {
|
if arg >= len(container.ContainerSections) {
|
||||||
return visited, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrUnreachableCode, arg, len(container.ContainerSections), i)
|
return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrUnreachableCode, arg, len(container.ContainerSections), i)
|
||||||
}
|
}
|
||||||
if ct := container.ContainerSections[arg]; len(ct.Data) != ct.DataSize {
|
if ct := container.ContainerSections[arg]; len(ct.Data) != ct.DataSize {
|
||||||
return visited, fmt.Errorf("%w: container %d, have %d, claimed %d, pos %d", ErrEOFCreateWithTruncatedSection, arg, len(ct.Data), ct.DataSize, i)
|
return nil, fmt.Errorf("%w: container %d, have %d, claimed %d, pos %d", ErrEOFCreateWithTruncatedSection, arg, len(ct.Data), ct.DataSize, i)
|
||||||
}
|
}
|
||||||
|
if _, ok := visitedSubcontainers[arg]; ok {
|
||||||
|
return nil, fmt.Errorf("section already referenced, arg :%d", arg)
|
||||||
|
}
|
||||||
|
// We need to store per subcontainer how it was referenced
|
||||||
|
if v, ok := visitedSubcontainers[arg]; ok && v != RefByEOFCreate {
|
||||||
|
return nil, fmt.Errorf("section already referenced, arg :%d", arg)
|
||||||
|
}
|
||||||
|
visitedSubcontainers[arg] = RefByEOFCreate
|
||||||
|
case op == STOP || op == RETURN:
|
||||||
|
if isInitCode {
|
||||||
|
return nil, ErrStopInInitCode
|
||||||
|
}
|
||||||
|
if hasReturnContract {
|
||||||
|
return nil, ErrStopAndReturnContract
|
||||||
|
}
|
||||||
|
hasStop = true
|
||||||
}
|
}
|
||||||
i += size
|
i += size
|
||||||
}
|
}
|
||||||
|
|
@ -126,16 +172,21 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable)
|
||||||
// Code sections may not "fall through" and require proper termination.
|
// Code sections may not "fall through" and require proper termination.
|
||||||
// Therefore, the last instruction must be considered terminal or RJUMP.
|
// Therefore, the last instruction must be considered terminal or RJUMP.
|
||||||
if !jt[op].terminal && op != RJUMP {
|
if !jt[op].terminal && op != RJUMP {
|
||||||
return visited, fmt.Errorf("%w: end with %s, pos %d", ErrInvalidCodeTermination, op, i)
|
return nil, fmt.Errorf("%w: end with %s, pos %d", ErrInvalidCodeTermination, op, i)
|
||||||
}
|
}
|
||||||
if paths, err := validateControlFlow2(code, section, container.Types, jt); err != nil {
|
if paths, err := validateControlFlow2(code, section, container.Types, jt); err != nil {
|
||||||
return visited, err
|
return nil, err
|
||||||
} else if paths != count {
|
} else if paths != count {
|
||||||
fmt.Printf("Paths: %v Count: %v\n", paths, count)
|
fmt.Printf("Paths: %v Count: %v\n", paths, count)
|
||||||
// TODO(matt): return actual position of unreachable code
|
// TODO(matt): return actual position of unreachable code
|
||||||
return visited, ErrUnreachableCode
|
return nil, ErrUnreachableCode
|
||||||
}
|
}
|
||||||
return visited, nil
|
return &ValidationResult{
|
||||||
|
VisitedCode: visitedCode,
|
||||||
|
VisitedSubContainers: visitedSubcontainers,
|
||||||
|
IsInitCode: hasReturnContract,
|
||||||
|
IsRuntime: hasStop,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkDest parses a relative offset at code[0:2] and checks if it is a valid jump destination.
|
// checkDest parses a relative offset at code[0:2] and checks if it is a valid jump destination.
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ func TestValidateCode(t *testing.T) {
|
||||||
Data: make([]byte, 0),
|
Data: make([]byte, 0),
|
||||||
ContainerSections: make([]*Container, 0),
|
ContainerSections: make([]*Container, 0),
|
||||||
}
|
}
|
||||||
_, err := validateCode(test.code, test.section, container, &pragueEOFInstructionSet)
|
_, err := validateCode(test.code, test.section, container, &pragueEOFInstructionSet, true)
|
||||||
if !errors.Is(err, test.err) {
|
if !errors.Is(err, test.err) {
|
||||||
t.Errorf("test %d (%s): unexpected error (want: %v, got: %v)", i, common.Bytes2Hex(test.code), test.err, err)
|
t.Errorf("test %d (%s): unexpected error (want: %v, got: %v)", i, common.Bytes2Hex(test.code), test.err, err)
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +274,7 @@ func BenchmarkRJUMPI(b *testing.B) {
|
||||||
}
|
}
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, err := validateCode(code, 0, container, &pragueEOFInstructionSet)
|
_, err := validateCode(code, 0, container, &pragueEOFInstructionSet, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -304,7 +304,7 @@ func BenchmarkRJUMPV(b *testing.B) {
|
||||||
}
|
}
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, err := validateCode(code, 0, container, &pragueEOFInstructionSet)
|
_, err := validateCode(code, 0, container, &pragueEOFInstructionSet, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -345,10 +345,10 @@ func BenchmarkEOFValidation(b *testing.B) {
|
||||||
var container2 Container
|
var container2 Container
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if err := container2.UnmarshalBinary(bin); err != nil {
|
if err := container2.UnmarshalBinary(bin, true); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := container2.ValidateCode(&pragueEOFInstructionSet); err != nil {
|
if err := container2.ValidateCode(&pragueEOFInstructionSet, true); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -395,10 +395,10 @@ func BenchmarkEOFValidation2(b *testing.B) {
|
||||||
var container2 Container
|
var container2 Container
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if err := container2.UnmarshalBinary(bin); err != nil {
|
if err := container2.UnmarshalBinary(bin, true); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := container2.ValidateCode(&pragueEOFInstructionSet); err != nil {
|
if err := container2.ValidateCode(&pragueEOFInstructionSet, true); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -444,10 +444,10 @@ func BenchmarkEOFValidation3(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
for k := 0; k < 40; k++ {
|
for k := 0; k < 40; k++ {
|
||||||
var container2 Container
|
var container2 Container
|
||||||
if err := container2.UnmarshalBinary(bin); err != nil {
|
if err := container2.UnmarshalBinary(bin, true); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := container2.ValidateCode(&pragueEOFInstructionSet); err != nil {
|
if err := container2.ValidateCode(&pragueEOFInstructionSet, true); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -473,7 +473,7 @@ func BenchmarkRJUMPI_2(b *testing.B) {
|
||||||
}
|
}
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, err := validateCode(code, 0, container, &pragueEOFInstructionSet)
|
_, err := validateCode(code, 0, container, &pragueEOFInstructionSet, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -483,7 +483,7 @@ func BenchmarkRJUMPI_2(b *testing.B) {
|
||||||
func FuzzUnmarshalBinary(f *testing.F) {
|
func FuzzUnmarshalBinary(f *testing.F) {
|
||||||
f.Fuzz(func(_ *testing.T, input []byte) {
|
f.Fuzz(func(_ *testing.T, input []byte) {
|
||||||
var container Container
|
var container Container
|
||||||
container.UnmarshalBinary(input)
|
container.UnmarshalBinary(input, true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -491,6 +491,6 @@ func FuzzValidate(f *testing.F) {
|
||||||
f.Fuzz(func(_ *testing.T, code []byte, maxStack uint16) {
|
f.Fuzz(func(_ *testing.T, code []byte, maxStack uint16) {
|
||||||
var container Container
|
var container Container
|
||||||
container.Types = append(container.Types, &FunctionMetadata{Input: 0, Output: 0x80, MaxStackHeight: maxStack})
|
container.Types = append(container.Types, &FunctionMetadata{Input: 0, Output: 0x80, MaxStackHeight: maxStack})
|
||||||
validateCode(code, 0, &container, &pragueEOFInstructionSet)
|
validateCode(code, 0, &container, &pragueEOFInstructionSet, true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue