compiler: make writeJumps return error for bad jumps

The script is invalid anyway so it is better to notify user.
This commit is contained in:
Evgenii Stratonikov 2020-02-21 11:57:24 +03:00
parent 5e229d84d4
commit 177b725dc1

View file

@ -1203,7 +1203,9 @@ func CodeGen(info *buildInfo) ([]byte, error) {
return nil, c.prog.Err return nil, c.prog.Err
} }
buf := c.prog.Bytes() buf := c.prog.Bytes()
c.writeJumps(buf) if err := c.writeJumps(buf); err != nil {
return nil, err
}
return buf, nil return buf, nil
} }
@ -1218,20 +1220,26 @@ func (c *codegen) resolveFuncDecls(f *ast.File) {
} }
} }
func (c *codegen) writeJumps(b []byte) { func (c *codegen) writeJumps(b []byte) error {
ctx := vm.NewContext(b) ctx := vm.NewContext(b)
for op, _, err := ctx.Next(); err == nil && ctx.NextIP() < len(b); op, _, err = ctx.Next() { for op, _, err := ctx.Next(); err == nil && ctx.NextIP() < len(b); op, _, err = ctx.Next() {
switch op { switch op {
case opcode.JMP, opcode.JMPIFNOT, opcode.JMPIF, opcode.CALL: case opcode.JMP, opcode.JMPIFNOT, opcode.JMPIF, opcode.CALL:
// we can't use arg returned by ctx.Next() because it is copied // we can't use arg returned by ctx.Next() because it is copied
arg := b[ctx.NextIP()-2:] nextIP := ctx.NextIP()
arg := b[nextIP-2:]
index := int16(binary.LittleEndian.Uint16(arg)) index := binary.LittleEndian.Uint16(arg)
if int(index) > len(c.l) || int(index) < 0 { if int(index) > len(c.l) {
continue return fmt.Errorf("unexpected label number: %d (max %d)", index, len(c.l))
} }
offset := uint16(c.l[index] - ctx.NextIP() + 3) offset := c.l[index] - nextIP + 3
binary.LittleEndian.PutUint16(arg, offset) if offset > math.MaxUint16 {
return fmt.Errorf("label offset is too big at the instruction %d: %d (max %d)",
nextIP-3, offset, math.MaxUint16)
}
binary.LittleEndian.PutUint16(arg, uint16(offset))
} }
} }
return nil
} }