Skip to content

Commit b875d6c

Browse files
committed
fix(vm): guard negative forward jump offsets
Disallow negative offsets for forward jump opcodes in the VM. The compiler only ever emits non-negative offsets, but a crafted Program or fuzzed bytecode could pass negative arguments for OpJump and the conditional jump variants, causing unsafe control flow. Now these opcodes panic with a clear error when given a negative offset. Signed-off-by: Ville Vesilehto <[email protected]>
1 parent 5ac4a1a commit b875d6c

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

vm/vm.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,29 +176,47 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
176176
vm.push(a.(string) == b.(string))
177177

178178
case OpJump:
179+
if arg < 0 {
180+
panic("negative jump offset is invalid")
181+
}
179182
vm.ip += arg
180183

181184
case OpJumpIfTrue:
185+
if arg < 0 {
186+
panic("negative jump offset is invalid")
187+
}
182188
if vm.current().(bool) {
183189
vm.ip += arg
184190
}
185191

186192
case OpJumpIfFalse:
193+
if arg < 0 {
194+
panic("negative jump offset is invalid")
195+
}
187196
if !vm.current().(bool) {
188197
vm.ip += arg
189198
}
190199

191200
case OpJumpIfNil:
201+
if arg < 0 {
202+
panic("negative jump offset is invalid")
203+
}
192204
if runtime.IsNil(vm.current()) {
193205
vm.ip += arg
194206
}
195207

196208
case OpJumpIfNotNil:
209+
if arg < 0 {
210+
panic("negative jump offset is invalid")
211+
}
197212
if !runtime.IsNil(vm.current()) {
198213
vm.ip += arg
199214
}
200215

201216
case OpJumpIfEnd:
217+
if arg < 0 {
218+
panic("negative jump offset is invalid")
219+
}
202220
scope := vm.scope()
203221
if scope.Index >= scope.Len {
204222
vm.ip += arg

vm/vm_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,3 +1331,34 @@ func TestVM_Limits(t *testing.T) {
13311331
})
13321332
}
13331333
}
1334+
1335+
func TestVM_OpJump_NegativeOffset(t *testing.T) {
1336+
program := vm.NewProgram(
1337+
file.Source{},
1338+
nil,
1339+
nil,
1340+
0,
1341+
nil,
1342+
[]vm.Opcode{
1343+
vm.OpInt,
1344+
vm.OpInt,
1345+
vm.OpJump,
1346+
vm.OpInt,
1347+
vm.OpJump,
1348+
},
1349+
[]int{
1350+
1,
1351+
2,
1352+
-2, // negative offset for a forward jump opcode
1353+
3,
1354+
-2,
1355+
},
1356+
nil,
1357+
nil,
1358+
nil,
1359+
)
1360+
1361+
_, err := vm.Run(program, nil)
1362+
require.Error(t, err)
1363+
require.Contains(t, err.Error(), "negative jump offset is invalid")
1364+
}

0 commit comments

Comments
 (0)