Catch missing input on empty bytecode buffer

This commit is contained in:
lash 2023-04-06 09:54:51 +01:00
parent f0bfff3a20
commit 6325ef4afd
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
3 changed files with 68 additions and 18 deletions

View File

@ -2,4 +2,5 @@ package state
const ( const (
FLAG_INMATCH = 1 FLAG_INMATCH = 1
FLAG_TERMINATE = 2
) )

View File

@ -57,6 +57,12 @@ func Run(b []byte, st *state.State, rs resource.Resource, ctx context.Context) (
if err != nil { if err != nil {
return b, err return b, err
} }
if len(b) == 0 {
b, err = RunDeadCheck(b, st, rs, ctx)
if err != nil {
return b, err
}
}
if len(b) == 0 { if len(b) == 0 {
return []byte{}, nil return []byte{}, nil
} }
@ -64,6 +70,36 @@ func Run(b []byte, st *state.State, rs resource.Resource, ctx context.Context) (
return b, nil return b, nil
} }
// RunDeadCheck determines whether a state of empty bytecode should result in termination.
//
// If there is remaining bytecode, this method is a noop.
//
// If input has not been matched, a default invalid input page should be generated aswell as a possiblity of return to last screen (or exit).
//
// If the termination flag has been set but not yet handled, execution is allowed to terminate.
func RunDeadCheck(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
if len(b) > 0 {
return b, nil
}
log.Printf("no code remaining, let's check if we terminate")
r, err := matchFlag(st, state.FLAG_TERMINATE, false)
if err != nil {
panic(err)
}
if r {
return b, nil
}
location := st.Where()
if location == "" {
return b, fmt.Errorf("dead runner with no current location")
}
b = NewLine(nil, MOVE, []string{"_catch"}, nil, nil)
b = NewLine(b, HALT, nil, nil, nil)
b = NewLine(b, MOVE, []string{location}, nil, nil)
log.Printf("code is now %x", b)
return b, nil
}
// RunMap executes the MAP opcode // RunMap executes the MAP opcode
func RunMap(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func RunMap(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
sym, b, err := ParseMap(b) sym, b, err := ParseMap(b)
@ -73,6 +109,7 @@ func RunMap(b []byte, st *state.State, rs resource.Resource, ctx context.Context
// RunMap executes the CATCH opcode // RunMap executes the CATCH opcode
func RunCatch(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func RunCatch(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
log.Printf("zzz %x", b)
sym, sig, mode, b, err := ParseCatch(b) sym, sig, mode, b, err := ParseCatch(b)
if err != nil { if err != nil {
return b, err return b, err

View File

@ -104,6 +104,7 @@ func TestRunLoadRender(t *testing.T) {
var err error var err error
b := NewLine(nil, LOAD, []string{"one"}, []byte{0x0a}, nil) b := NewLine(nil, LOAD, []string{"one"}, []byte{0x0a}, nil)
b = NewLine(b, HALT, nil, nil, nil)
b, err = Run(b, &st, &rs, context.TODO()) b, err = Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -127,11 +128,13 @@ func TestRunLoadRender(t *testing.T) {
} }
b = NewLine(nil, LOAD, []string{"two"}, []byte{0x0a}, nil) b = NewLine(nil, LOAD, []string{"two"}, []byte{0x0a}, nil)
b = NewLine(b, HALT, nil, nil, nil)
b, err = Run(b, &st, &rs, context.TODO()) b, err = Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
b = NewLine(nil, MAP, []string{"one"}, nil, nil) b = NewLine(nil, MAP, []string{"one"}, nil, nil)
b = NewLine(b, HALT, nil, nil, nil)
_, err = Run(b, &st, &rs, context.TODO()) _, err = Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -155,6 +158,7 @@ func TestRunMultiple(t *testing.T) {
rs := TestResource{} rs := TestResource{}
b := NewLine(nil, LOAD, []string{"one"}, []byte{0x00}, nil) b := NewLine(nil, LOAD, []string{"one"}, []byte{0x00}, nil)
b = NewLine(b, LOAD, []string{"two"}, []byte{42}, nil) b = NewLine(b, LOAD, []string{"two"}, []byte{42}, nil)
b = NewLine(b, HALT, nil, nil, nil)
b, err := Run(b, &st, &rs, context.TODO()) b, err := Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -167,33 +171,35 @@ func TestRunMultiple(t *testing.T) {
func TestRunReload(t *testing.T) { func TestRunReload(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{} rs := TestResource{}
b := NewLine(nil, LOAD, []string{"dyn"}, nil, []uint8{0}) b := NewLine(nil, MOVE, []string{"root"}, nil, nil)
b = NewLine(b, LOAD, []string{"dyn"}, nil, []uint8{0})
b = NewLine(b, MAP, []string{"dyn"}, nil, nil) b = NewLine(b, MAP, []string{"dyn"}, nil, nil)
b = NewLine(b, HALT, nil, nil, nil)
_, err := Run(b, &st, &rs, context.TODO()) _, err := Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Fatal(err)
} }
r, err := st.Val("dyn") r, err := st.Val("dyn")
if err != nil { if err != nil {
t.Error(err) t.Fatal(err)
} }
if r != "three" { if r != "three" {
t.Errorf("expected result 'three', got %v", r) t.Fatalf("expected result 'three', got %v", r)
} }
dynVal = "baz" dynVal = "baz"
b = []byte{} b = NewLine(nil, RELOAD, []string{"dyn"}, nil, nil)
b = NewLine(b, RELOAD, []string{"dyn"}, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
_, err = Run(b, &st, &rs, context.TODO()) _, err = Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Fatal(err)
} }
r, err = st.Val("dyn") r, err = st.Val("dyn")
if err != nil { if err != nil {
t.Error(err) t.Fatal(err)
} }
log.Printf("dun now %s", r) log.Printf("dun now %s", r)
if r != "baz" { if r != "baz" {
t.Errorf("expected result 'baz', got %v", r) t.Fatalf("expected result 'baz', got %v", r)
} }
} }
@ -225,7 +231,8 @@ func TestRunArg(t *testing.T) {
input := []byte("bar") input := []byte("bar")
_ = st.SetInput(input) _ = st.SetInput(input)
bi := NewLine([]byte{}, INCMP, []string{"bar", "baz"}, nil, nil) bi := NewLine(nil, INCMP, []string{"bar", "baz"}, nil, nil)
bi = NewLine(bi, HALT, nil, nil, nil)
b, err := Run(bi, &st, &rs, context.TODO()) b, err := Run(bi, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -252,6 +259,7 @@ func TestRunInputHandler(t *testing.T) {
bi = NewLine(bi, LOAD, []string{"two"}, []byte{0x03}, nil) bi = NewLine(bi, LOAD, []string{"two"}, []byte{0x03}, nil)
bi = NewLine(bi, MAP, []string{"one"}, nil, nil) bi = NewLine(bi, MAP, []string{"one"}, nil, nil)
bi = NewLine(bi, MAP, []string{"two"}, nil, nil) bi = NewLine(bi, MAP, []string{"two"}, nil, nil)
bi = NewLine(bi, HALT, nil, nil, nil)
var err error var err error
_, err = Run(bi, &st, &rs, context.TODO()) _, err = Run(bi, &st, &rs, context.TODO())
@ -271,21 +279,22 @@ func TestRunArgInvalid(t *testing.T) {
_ = st.SetInput([]byte("foo")) _ = st.SetInput([]byte("foo"))
var err error var err error
b := NewLine([]byte{}, INCMP, []string{"bar", "baz"}, nil, nil) st.Down("root")
b = NewLine(b, CATCH, []string{"_catch"}, []byte{state.FLAG_INMATCH}, []uint8{1}) b := NewLine(nil, INCMP, []string{"bar", "baz"}, nil, nil)
//b = NewLine(b, CATCH, []string{"_catch"}, []byte{state.FLAG_INMATCH}, []uint8{1})
b, err = Run(b, &st, &rs, context.TODO()) b, err = Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Fatal(err)
} }
l := len(b) expect := NewLine(nil, MOVE, []string{"root"}, nil, nil)
if l != 0 { if !bytes.Equal(b, expect) {
t.Errorf("expected empty remainder, got length %v: %v", l, b) t.Fatalf("expected:\n\t%x\ngot:\b\t%x\n", expect, b)
} }
r := st.Where() r := st.Where()
if r != "_catch" { if r != "_catch" {
t.Errorf("expected where-state _catch, got %v", r) t.Fatalf("expected where-state _catch, got %v", r)
} }
} }
@ -298,6 +307,7 @@ func TestRunMenu(t *testing.T) {
b := NewLine(nil, MOVE, []string{"foo"}, nil, nil) b := NewLine(nil, MOVE, []string{"foo"}, nil, nil)
b = NewLine(b, MOUT, []string{"0", "one"}, nil, nil) b = NewLine(b, MOUT, []string{"0", "one"}, nil, nil)
b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil) b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil)
b = NewLine(b, HALT, nil, nil, nil)
b, err = Run(b, &st, &rs, context.TODO()) b, err = Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
@ -331,6 +341,7 @@ func TestRunMenuBrowse(t *testing.T) {
b = NewLine(b, MPREV, []string{"22", "two"}, nil, nil) b = NewLine(b, MPREV, []string{"22", "two"}, nil, nil)
b = NewLine(b, MOUT, []string{"0", "one"}, nil, nil) b = NewLine(b, MOUT, []string{"0", "one"}, nil, nil)
b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil) b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil)
b = NewLine(b, HALT, nil, nil, nil)
b, err = Run(b, &st, &rs, context.TODO()) b, err = Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
@ -350,3 +361,4 @@ func TestRunMenuBrowse(t *testing.T) {
t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect, r) t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect, r)
} }
} }