WIP Add termination handler in engine

This commit is contained in:
lash 2023-04-06 10:08:40 +01:00
parent 6325ef4afd
commit a3073f6189
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
7 changed files with 47 additions and 28 deletions

View File

@ -321,7 +321,6 @@ func(bt *Batcher) MenuExit(w io.Writer) (int, error) {
}
bt.inMenu = false
b := bt.menuProcessor.ToLines()
log.Printf("tolines %v", b)
return w.Write(b)
}

View File

@ -41,7 +41,7 @@ func main() {
os.Exit(1)
}
in = strings.TrimSpace(in)
err = en.Exec([]byte(in), ctx)
running, err = en.Exec([]byte(in), ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "execution terminated: %v\n", err)
os.Exit(1)
@ -50,4 +50,5 @@ func main() {
en.WriteResult(b)
fmt.Println(b.String())
}
}

View File

@ -59,22 +59,38 @@ func(en *Engine) Init(sym string, ctx context.Context) error {
// - input is objectively invalid (too long etc)
// - no current bytecode is available
// - input processing against bytcode failed
func (en *Engine) Exec(input []byte, ctx context.Context) error {
func (en *Engine) Exec(input []byte, ctx context.Context) (bool, error) {
err := en.st.SetInput(input)
if err != nil {
return err
return false, err
}
log.Printf("new execution with input '%s' (0x%x)", input, input)
code, err := en.st.GetCode()
if err != nil {
return err
return false, err
}
if len(code) == 0 {
return fmt.Errorf("no code to execute")
return false, fmt.Errorf("no code to execute")
}
code, err = vm.Run(code, en.st, en.rs, ctx)
if err != nil {
return false, err
}
v, err := en.st.MatchFlag(state.FLAG_TERMINATE, false)
if err != nil {
return false, err
}
if v {
if len(code) > 0 {
log.Printf("terminated with code remaining: %x", code)
}
return false, nil
}
en.st.SetCode(code)
return err
return true, nil
}
// WriteResult writes the output of the last vm execution to the given writer.

View File

@ -97,7 +97,7 @@ func TestEngineInit(t *testing.T) {
}
input := []byte("1")
err = en.Exec(input, ctx)
_, err = en.Exec(input, ctx)
if err != nil {
t.Fatal(err)
}

View File

@ -135,6 +135,26 @@ func(st *State) FlagByteSize() uint8 {
return uint8(len(st.Flags))
}
// MatchFlag matches the current state of the given flag.
//
// The flag is specified given its bit index in the bit field.
//
// If invertMatch is set, a positive result will be returned if the flag is not set.
func(st *State) MatchFlag(sig uint32, invertMatch bool) (bool, error) {
r, err := st.GetFlag(sig)
if err != nil {
return false, err
}
if invertMatch {
if !r {
return true, nil
}
} else if r {
return true, nil
}
return false, nil
}
// GetIndex scans a byte slice in same order as in storage, and returns the index of the first set bit.
//
// If the given byte slice is too small for the bit field bitsize, the check will terminate at end-of-data without error.

View File

@ -82,7 +82,7 @@ func RunDeadCheck(b []byte, st *state.State, rs resource.Resource, ctx context.C
return b, nil
}
log.Printf("no code remaining, let's check if we terminate")
r, err := matchFlag(st, state.FLAG_TERMINATE, false)
r, err := st.MatchFlag(state.FLAG_TERMINATE, false)
if err != nil {
panic(err)
}
@ -114,7 +114,7 @@ func RunCatch(b []byte, st *state.State, rs resource.Resource, ctx context.Conte
if err != nil {
return b, err
}
r, err := matchFlag(st, sig, mode)
r, err := st.MatchFlag(sig, mode)
if err != nil {
return b, err
}
@ -132,7 +132,7 @@ func RunCroak(b []byte, st *state.State, rs resource.Resource, ctx context.Conte
if err != nil {
return b, err
}
r, err := matchFlag(st, sig, mode)
r, err := st.MatchFlag(sig, mode)
if err != nil {
return b, err
}

View File

@ -3,8 +3,6 @@ package vm
import (
"encoding/binary"
"fmt"
"git.defalsify.org/festive/state"
)
// NewLine creates a new instruction line for the VM.
@ -177,21 +175,6 @@ func parseSig(b []byte) (uint32, bool, []byte, error) {
return sig, matchmode, b, nil
}
// TODO: move to state
func matchFlag(st *state.State, sig uint32, invertMatch bool) (bool, error) {
r, err := st.GetFlag(sig)
if err != nil {
return false, err
}
if invertMatch {
if !r {
return true, nil
}
} else if r {
return true, nil
}
return false, nil
}
// split bytecode into head and b using length-prefixed bitfield
func byteSplit(b []byte) ([]byte, []byte, error) {