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 bt.inMenu = false
b := bt.menuProcessor.ToLines() b := bt.menuProcessor.ToLines()
log.Printf("tolines %v", b)
return w.Write(b) return w.Write(b)
} }

View File

@ -41,7 +41,7 @@ func main() {
os.Exit(1) os.Exit(1)
} }
in = strings.TrimSpace(in) in = strings.TrimSpace(in)
err = en.Exec([]byte(in), ctx) running, err = en.Exec([]byte(in), ctx)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "execution terminated: %v\n", err) fmt.Fprintf(os.Stderr, "execution terminated: %v\n", err)
os.Exit(1) os.Exit(1)
@ -50,4 +50,5 @@ func main() {
en.WriteResult(b) en.WriteResult(b)
fmt.Println(b.String()) 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) // - input is objectively invalid (too long etc)
// - no current bytecode is available // - no current bytecode is available
// - input processing against bytcode failed // - 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) err := en.st.SetInput(input)
if err != nil { if err != nil {
return err return false, err
} }
log.Printf("new execution with input '%s' (0x%x)", input, input) log.Printf("new execution with input '%s' (0x%x)", input, input)
code, err := en.st.GetCode() code, err := en.st.GetCode()
if err != nil { if err != nil {
return err return false, err
} }
if len(code) == 0 { 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) 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) en.st.SetCode(code)
return err
return true, nil
} }
// WriteResult writes the output of the last vm execution to the given writer. // 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") input := []byte("1")
err = en.Exec(input, ctx) _, err = en.Exec(input, ctx)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -135,6 +135,26 @@ func(st *State) FlagByteSize() uint8 {
return uint8(len(st.Flags)) 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. // 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. // 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 return b, nil
} }
log.Printf("no code remaining, let's check if we terminate") 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 { if err != nil {
panic(err) panic(err)
} }
@ -114,7 +114,7 @@ func RunCatch(b []byte, st *state.State, rs resource.Resource, ctx context.Conte
if err != nil { if err != nil {
return b, err return b, err
} }
r, err := matchFlag(st, sig, mode) r, err := st.MatchFlag(sig, mode)
if err != nil { if err != nil {
return b, err return b, err
} }
@ -132,7 +132,7 @@ func RunCroak(b []byte, st *state.State, rs resource.Resource, ctx context.Conte
if err != nil { if err != nil {
return b, err return b, err
} }
r, err := matchFlag(st, sig, mode) r, err := st.MatchFlag(sig, mode)
if err != nil { if err != nil {
return b, err return b, err
} }

View File

@ -3,8 +3,6 @@ package vm
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"git.defalsify.org/festive/state"
) )
// NewLine creates a new instruction line for the VM. // 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 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 // split bytecode into head and b using length-prefixed bitfield
func byteSplit(b []byte) ([]byte, []byte, error) { func byteSplit(b []byte) ([]byte, []byte, error) {