mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 13:41:37 +00:00
Merge pull request #1989 from nspcc-dev/compiler-notify-name
compiler: check event name length in `runtime.Notify`
This commit is contained in:
commit
ebff8be20a
5 changed files with 87 additions and 15 deletions
2
cli/testdata/verify.yml
vendored
2
cli/testdata/verify.yml
vendored
|
@ -1,5 +1,5 @@
|
||||||
name: Test verify
|
name: Test verify
|
||||||
Events:
|
events:
|
||||||
- name: OnNEP11Payment
|
- name: OnNEP11Payment
|
||||||
parameters:
|
parameters:
|
||||||
- name: from
|
- name: from
|
||||||
|
|
|
@ -959,20 +959,6 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
ast.Walk(c, n.Fun)
|
ast.Walk(c, n.Fun)
|
||||||
emit.Opcodes(c.prog.BinWriter, opcode.CALLA)
|
emit.Opcodes(c.prog.BinWriter, opcode.CALLA)
|
||||||
case isSyscall(f):
|
case isSyscall(f):
|
||||||
if f.pkg.Name() == "runtime" && f.name == "Notify" {
|
|
||||||
tv := c.typeAndValueOf(n.Args[0])
|
|
||||||
params := make([]string, 0, len(n.Args[1:]))
|
|
||||||
for _, p := range n.Args[1:] {
|
|
||||||
st, _ := c.scAndVMTypeFromExpr(p)
|
|
||||||
params = append(params, st.String())
|
|
||||||
}
|
|
||||||
// Sometimes event name is stored in a var.
|
|
||||||
// Skip in this case.
|
|
||||||
if tv.Value != nil {
|
|
||||||
name := constant.StringVal(tv.Value)
|
|
||||||
c.emittedEvents[name] = append(c.emittedEvents[name], params)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.convertSyscall(f, n)
|
c.convertSyscall(f, n)
|
||||||
default:
|
default:
|
||||||
emit.Call(c.prog.BinWriter, opcode.CALLL, f.label)
|
emit.Call(c.prog.BinWriter, opcode.CALLL, f.label)
|
||||||
|
|
|
@ -9,6 +9,8 @@ import (
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/compiler"
|
"github.com/nspcc-dev/neo-go/pkg/compiler"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -130,3 +132,46 @@ func TestOnPayableChecks(t *testing.T) {
|
||||||
require.Error(t, compileAndCheck(t, src))
|
require.Error(t, compileAndCheck(t, src))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEventWarnings(t *testing.T) {
|
||||||
|
src := `package payable
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
func Main() { runtime.Notify("Event", 1) }`
|
||||||
|
|
||||||
|
_, di, err := compiler.CompileWithDebugInfo("eventTest", strings.NewReader(src))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Run("event it missing from config", func(t *testing.T) {
|
||||||
|
_, err = compiler.CreateManifest(di, &compiler.Options{})
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
t.Run("suppress", func(t *testing.T) {
|
||||||
|
_, err = compiler.CreateManifest(di, &compiler.Options{NoEventsCheck: true})
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
t.Run("wrong parameter number", func(t *testing.T) {
|
||||||
|
_, err = compiler.CreateManifest(di, &compiler.Options{
|
||||||
|
ContractEvents: []manifest.Event{{Name: "Event"}},
|
||||||
|
})
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
t.Run("wrong parameter type", func(t *testing.T) {
|
||||||
|
_, err = compiler.CreateManifest(di, &compiler.Options{
|
||||||
|
ContractEvents: []manifest.Event{{
|
||||||
|
Name: "Event",
|
||||||
|
Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.StringType)},
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
t.Run("good", func(t *testing.T) {
|
||||||
|
_, err = compiler.CreateManifest(di, &compiler.Options{
|
||||||
|
ContractEvents: []manifest.Event{{
|
||||||
|
Name: "Event",
|
||||||
|
Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.IntegerType)},
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package compiler
|
package compiler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
"go/constant"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
)
|
)
|
||||||
|
@ -27,6 +30,8 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) {
|
||||||
pkg := c.buildInfo.program.Package(f.pkg.Path())
|
pkg := c.buildInfo.program.Package(f.pkg.Path())
|
||||||
sig := c.typeOf(n.Fun).(*types.Signature)
|
sig := c.typeOf(n.Fun).(*types.Signature)
|
||||||
|
|
||||||
|
c.processNotify(f, n.Args)
|
||||||
|
|
||||||
// When inlined call is used during global initialization
|
// When inlined call is used during global initialization
|
||||||
// there is no func scope, thus this if.
|
// there is no func scope, thus this if.
|
||||||
if c.scope == nil {
|
if c.scope == nil {
|
||||||
|
@ -114,3 +119,28 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) {
|
||||||
c.importMap = oldMap
|
c.importMap = oldMap
|
||||||
c.pkgInfoInline = c.pkgInfoInline[:len(c.pkgInfoInline)-1]
|
c.pkgInfoInline = c.pkgInfoInline[:len(c.pkgInfoInline)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *codegen) processNotify(f *funcScope, args []ast.Expr) {
|
||||||
|
if f != nil && f.pkg.Path() == interopPrefix+"/runtime" && f.name == "Notify" {
|
||||||
|
// Sometimes event name is stored in a var.
|
||||||
|
// Skip in this case.
|
||||||
|
tv := c.typeAndValueOf(args[0])
|
||||||
|
if tv.Value == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params := make([]string, 0, len(args[1:]))
|
||||||
|
for _, p := range args[1:] {
|
||||||
|
st, _ := c.scAndVMTypeFromExpr(p)
|
||||||
|
params = append(params, st.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
name := constant.StringVal(tv.Value)
|
||||||
|
if len(name) > runtime.MaxEventNameLen {
|
||||||
|
c.prog.Err = fmt.Errorf("event name '%s' should be less than %d",
|
||||||
|
name, runtime.MaxEventNameLen)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.emittedEvents[name] = append(c.emittedEvents[name], params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -188,6 +188,17 @@ func TestNotify(t *testing.T) {
|
||||||
assert.Equal(t, exp0, s.events[0].Item.Value())
|
assert.Equal(t, exp0, s.events[0].Item.Value())
|
||||||
assert.Equal(t, "single", s.events[1].Name)
|
assert.Equal(t, "single", s.events[1].Name)
|
||||||
assert.Equal(t, []stackitem.Item{}, s.events[1].Item.Value())
|
assert.Equal(t, []stackitem.Item{}, s.events[1].Item.Value())
|
||||||
|
|
||||||
|
t.Run("long event name", func(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
func Main(arg int) {
|
||||||
|
runtime.Notify("long event12345678901234567890123")
|
||||||
|
}`
|
||||||
|
|
||||||
|
_, _, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(src))
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSyscallInGlobalInit(t *testing.T) {
|
func TestSyscallInGlobalInit(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue