Merge pull request #1226 from nspcc-dev/fix/pusha

vm: make offset in PUSHA relative
This commit is contained in:
Roman Khimov 2020-07-23 23:40:21 +03:00 committed by GitHub
commit 2800179ce0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 7 additions and 17 deletions

View file

@ -1533,12 +1533,7 @@ func (c *codegen) writeJumps(b []byte) error {
if int(index) > len(c.l) { if int(index) > len(c.l) {
return fmt.Errorf("unexpected label number: %d (max %d)", index, len(c.l)) return fmt.Errorf("unexpected label number: %d (max %d)", index, len(c.l))
} }
var offset int offset := c.l[index] - nextIP + 5
if op == opcode.PUSHA {
offset = c.l[index]
} else {
offset = c.l[index] - nextIP + 5
}
if offset > math.MaxInt32 || offset < math.MinInt32 { if offset > math.MaxInt32 || offset < math.MinInt32 {
return fmt.Errorf("label offset is too big at the instruction %d: %d (max %d, min %d)", return fmt.Errorf("label offset is too big at the instruction %d: %d (max %d, min %d)",
nextIP-5, offset, math.MaxInt32, math.MinInt32) nextIP-5, offset, math.MaxInt32, math.MinInt32)

View file

@ -192,16 +192,14 @@ func (v *VM) PrintOps() {
opcode.JMPGT, opcode.JMPGE, opcode.JMPLE, opcode.JMPLT, opcode.JMPGT, opcode.JMPGE, opcode.JMPLE, opcode.JMPLT,
opcode.JMPL, opcode.JMPIFL, opcode.JMPIFNOTL, opcode.CALLL, opcode.JMPL, opcode.JMPIFL, opcode.JMPIFNOTL, opcode.CALLL,
opcode.JMPEQL, opcode.JMPNEL, opcode.JMPEQL, opcode.JMPNEL,
opcode.JMPGTL, opcode.JMPGEL, opcode.JMPLEL, opcode.JMPLTL: opcode.JMPGTL, opcode.JMPGEL, opcode.JMPLEL, opcode.JMPLTL,
opcode.PUSHA:
offset, rOffset, err := v.calcJumpOffset(ctx, parameter) offset, rOffset, err := v.calcJumpOffset(ctx, parameter)
if err != nil { if err != nil {
desc = fmt.Sprintf("ERROR: %v", err) desc = fmt.Sprintf("ERROR: %v", err)
} else { } else {
desc = fmt.Sprintf("%d (%d/%x)", offset, rOffset, parameter) desc = fmt.Sprintf("%d (%d/%x)", offset, rOffset, parameter)
} }
case opcode.PUSHA:
offset := int32(binary.LittleEndian.Uint32(parameter))
desc = fmt.Sprintf("%d (%x)", offset, parameter)
case opcode.INITSSLOT: case opcode.INITSSLOT:
desc = fmt.Sprint(parameter[0]) desc = fmt.Sprint(parameter[0])
case opcode.INITSLOT: case opcode.INITSLOT:
@ -535,11 +533,8 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
v.estack.PushVal(parameter) v.estack.PushVal(parameter)
case opcode.PUSHA: case opcode.PUSHA:
n := int32(binary.LittleEndian.Uint32(parameter)) n := v.getJumpOffset(ctx, parameter)
if n < 0 || int(n) > len(ctx.prog) { ptr := stackitem.NewPointer(n, ctx.prog)
panic(fmt.Sprintf("invalid pointer offset (%d)", n))
}
ptr := stackitem.NewPointer(int(n), ctx.prog)
v.estack.PushVal(ptr) v.estack.PushVal(ptr)
case opcode.PUSHNULL: case opcode.PUSHNULL:

View file

@ -956,8 +956,8 @@ func TestPUSHA(t *testing.T) {
t.Run("Negative", getTestFuncForVM(makeProgram(opcode.PUSHA, 0xFF, 0xFF, 0xFF, 0xFF), nil)) t.Run("Negative", getTestFuncForVM(makeProgram(opcode.PUSHA, 0xFF, 0xFF, 0xFF, 0xFF), nil))
t.Run("TooBig", getTestFuncForVM(makeProgram(opcode.PUSHA, 10, 0, 0, 0), nil)) t.Run("TooBig", getTestFuncForVM(makeProgram(opcode.PUSHA, 10, 0, 0, 0), nil))
t.Run("Good", func(t *testing.T) { t.Run("Good", func(t *testing.T) {
prog := makeProgram(opcode.PUSHA, 2, 0, 0, 0) prog := makeProgram(opcode.NOP, opcode.PUSHA, 2, 0, 0, 0)
runWithArgs(t, prog, stackitem.NewPointer(2, prog)) runWithArgs(t, prog, stackitem.NewPointer(3, prog))
}) })
} }