From bd84a5b969165e80689e380bf8dcba012ae3048a Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sat, 20 Nov 2021 18:12:17 -1000 Subject: [PATCH] Restrict global and function references to memory size --- gen/operand.go | 4 ++-- gen/rand.go | 10 ++++++++++ test/gen_test.go | 12 +++++++++++- test/rand_test.go | 12 ++++++------ vm/stackframe.go | 4 +++- vm/state.go | 4 +++- 6 files changed, 35 insertions(+), 11 deletions(-) diff --git a/gen/operand.go b/gen/operand.go index 0fc659b..8545414 100644 --- a/gen/operand.go +++ b/gen/operand.go @@ -12,10 +12,10 @@ func randOperand(t vm.OperandNumericType) *vm.Operand { switch op.Type { case vm.GlobalMemoryIndex: - op.Value = RandBiasedUint64() + op.Value = RandBiasedUint64n(vm.GlobalMemorySize) case vm.FunctionMemoryIndex: - op.Value = RandBiasedUint64() + op.Value = RandBiasedUint64n(vm.FunctionMemorySize) case vm.Literal: switch t { diff --git a/gen/rand.go b/gen/rand.go index 021ee65..fbf1012 100644 --- a/gen/rand.go +++ b/gen/rand.go @@ -9,6 +9,16 @@ func RandBiasedUint64() uint64 { return (rand.Uint64() | 0x8000000000000000) >> rand.Intn(65) } +// Like RandBiasedUint64() but always returns < n +func RandBiasedUint64n(n uint64) uint64 { + for { + ret := RandBiasedUint64() + if ret < n { + return ret + } + } +} + // Generate a random int64 with an even distribution of the tuple // {sign, bits.Len64(math.Abs())} func RandBiasedInt64() uint64 { diff --git a/test/gen_test.go b/test/gen_test.go index 6a100ff..b8ae5ae 100644 --- a/test/gen_test.go +++ b/test/gen_test.go @@ -3,7 +3,17 @@ package test import "testing" import "github.com/firestuff/subcoding/gen" +import "github.com/firestuff/subcoding/asm" func TestRandProgram(t *testing.T) { - gen.RandProgram() + for i := 0; i < 100; i++ { + prog := gen.RandProgram() + + src, err := asm.Disassemble(prog) + if err != nil { + t.Fatal(err) + } + + t.Log(src) + } } diff --git a/test/rand_test.go b/test/rand_test.go index d13c54e..19c7629 100644 --- a/test/rand_test.go +++ b/test/rand_test.go @@ -29,8 +29,8 @@ func TestRandBiasedUint64(t *testing.T) { } } - if max - min > max / 10 { - t.Fatalf("Variance greater than allowed: %d > %d (max=%d min=%d)", max - min, max / 10, max, min) + if max-min > max/10 { + t.Fatalf("Variance greater than allowed: %d > %d (max=%d min=%d)", max-min, max/10, max, min) } } @@ -48,9 +48,9 @@ func TestRandBiasedInt64(t *testing.T) { case val == 0: buckets[63]++ case val < 0: - buckets[63 + bits.Len64(uint64(val * -1))]++ + buckets[63+bits.Len64(uint64(val*-1))]++ case val > 0: - buckets[63 - bits.Len64(uint64(val))]++ + buckets[63-bits.Len64(uint64(val))]++ } } @@ -67,7 +67,7 @@ func TestRandBiasedInt64(t *testing.T) { } } - if max - min > max / 10 { - t.Fatalf("Variance greater than allowed: %d > %d (max=%d min=%d)", max - min, max / 10, max, min) + if max-min > max/10 { + t.Fatalf("Variance greater than allowed: %d > %d (max=%d min=%d)", max-min, max/10, max, min) } } diff --git a/vm/stackframe.go b/vm/stackframe.go index bd93c2e..2cdba2c 100644 --- a/vm/stackframe.go +++ b/vm/stackframe.go @@ -1,5 +1,7 @@ package vm +const FunctionMemorySize = 16 + type stackFrame struct { previousFunctionIndex int64 previousInstructionIndex int64 @@ -10,6 +12,6 @@ func newStackFrame(state *State) *stackFrame { return &stackFrame{ previousFunctionIndex: state.functionIndex, previousInstructionIndex: state.instructionIndex, - functionMemory: NewMemory(16), + functionMemory: NewMemory(FunctionMemorySize), } } diff --git a/vm/state.go b/vm/state.go index 2728c5f..dc734c5 100644 --- a/vm/state.go +++ b/vm/state.go @@ -2,6 +2,8 @@ package vm import "fmt" +const GlobalMemorySize = 16 + type State struct { running bool err error @@ -18,7 +20,7 @@ type State struct { func NewState(prog *Program) (*State, error) { return &State{ program: prog, - globalMemory: NewMemory(16), + globalMemory: NewMemory(GlobalMemorySize), }, nil }