From 8305389852d93b097956b8445dec350112f62374 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 11 Jan 2023 16:21:40 +0300 Subject: [PATCH] compiler: don't panic, return error for strange range loops See #2870. --- pkg/compiler/codegen.go | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index fb5c75ef6..50edd84c9 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -1301,25 +1301,45 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { emit.Opcodes(c.prog.BinWriter, opcode.OVER, opcode.OVER) emit.Jmp(c.prog.BinWriter, opcode.JMPLEL, end) - var keyLoaded bool - needValue := n.Value != nil && n.Value.(*ast.Ident).Name != "_" - if n.Key != nil && n.Key.(*ast.Ident).Name != "_" { + var ( + haveKey bool + haveVal bool + keyIdent *ast.Ident + keyLoaded bool + valIdent *ast.Ident + ) + if n.Key != nil { + keyIdent, haveKey = n.Key.(*ast.Ident) + if !haveKey { + c.prog.Err = errors.New("only simple identifiers can be used for range loop keys (see #2870)") + return nil + } + haveKey = (keyIdent.Name != "_") + } + if n.Value != nil { + valIdent, haveVal = n.Value.(*ast.Ident) + if !haveVal { + c.prog.Err = errors.New("only simple identifiers can be used for range loop values (see #2870)") + return nil + } + haveVal = (valIdent.Name != "_") + } + if haveKey { if isMap { c.rangeLoadKey() - if needValue { + if haveVal { emit.Opcodes(c.prog.BinWriter, opcode.DUP) keyLoaded = true } } else { emit.Opcodes(c.prog.BinWriter, opcode.DUP) } - keyIdent := n.Key.(*ast.Ident) if n.Tok == token.DEFINE { c.scope.newLocal(keyIdent.Name) } c.emitStoreVar("", keyIdent.Name) } - if needValue { + if haveVal { if !isMap || !keyLoaded { c.rangeLoadKey() } @@ -1331,7 +1351,6 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { opcode.SWAP, // key should be on top opcode.PICKITEM) } - valIdent := n.Value.(*ast.Ident) if n.Tok == token.DEFINE { c.scope.newLocal(valIdent.Name) }