go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

commit 3558025e4e3e75dea7a54bd2fcb994b5866b96c7
parent f1cf589ad6e8b081b1a92f1350bc47f60e13f123
Author: lash <dev@holbrook.no>
Date:   Sun, 15 Sep 2024 02:28:19 +0100

Add prefix check for pre-vm code

Diffstat:
Aexamples/first/Makefile | 10++++++++++
Aexamples/first/foo | 1+
Aexamples/first/foo.vis | 2++
Aexamples/first/main.go | 188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aexamples/first/root | 1+
Aexamples/first/root.vis | 2++
Mstate/state.go | 3++-
7 files changed, 206 insertions(+), 1 deletion(-)

diff --git a/examples/first/Makefile b/examples/first/Makefile @@ -0,0 +1,10 @@ +INPUTS = $(wildcard ./*.vis) +TXTS = $(wildcard ./*.txt.orig) + +%.vis: + go run ../../dev/asm $(basename $@).vis > $(basename $@).bin + +all: $(INPUTS) $(TXTS) + +%.txt.orig: + cp -v $(basename $@).orig $(basename $@) diff --git a/examples/first/foo b/examples/first/foo @@ -0,0 +1 @@ +No access diff --git a/examples/first/foo.vis b/examples/first/foo.vis @@ -0,0 +1,2 @@ +HALT +MOVE ^ diff --git a/examples/first/main.go b/examples/first/main.go @@ -0,0 +1,188 @@ +// Example: Sub-machine using the first function feature in engine +package main + +import ( + "context" + "encoding/hex" + "errors" + "flag" + "fmt" + "os" + "path" + "crypto/rand" + "crypto/sha256" + + testdataloader "github.com/peteole/testdata-loader" + + "git.defalsify.org/vise.git/db" + "git.defalsify.org/vise.git/engine" + "git.defalsify.org/vise.git/persist" + "git.defalsify.org/vise.git/resource" + "git.defalsify.org/vise.git/state" + "git.defalsify.org/vise.git/logging" + fsdb "git.defalsify.org/vise.git/db/fs" +) + +const ( + USER_CHALLENGED = iota + state.FLAG_USERSTART + USER_FAILED + USER_SUCCEEDED +) + +var ( + logg = logging.NewVanilla() + baseDir = testdataloader.GetBasePath() + scriptDir = path.Join(baseDir, "examples", "first") + storeDir = path.Join(scriptDir, ".state") + authStoreDir = path.Join(scriptDir, ".auth") +) + +type firstAuthResource struct { + st *state.State + store db.Db +} + +func(f *firstAuthResource) challenge(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var err error + var r resource.Result + + if len(input) == 0 { + return r, nil + } + if input[0] != 0x25 { // % + return r, nil + } + + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return r, errors.New("missing session") + } + + if !f.st.GetFlag(USER_CHALLENGED) { + succeed := f.st.GetFlag(USER_SUCCEEDED) + failed := f.st.GetFlag(USER_FAILED) + if succeed { + return r, nil + } else { + if failed { + r.FlagReset = append(r.FlagReset, USER_FAILED) + } + b := make([]byte, 32) + _, err = rand.Read(b) + if err != nil { + return r, err + } + f.store.SetPrefix(db.DATATYPE_USERDATA) + f.store.SetSession(sessionId) + err := f.store.Put(ctx, []byte("challenge"), b) + if err != nil { + return r, err + } + r.FlagSet = append(r.FlagSet, USER_CHALLENGED) + r.FlagSet = append(r.FlagSet, state.FLAG_TERMINATE) + r.Content = hex.EncodeToString(b) + return r, nil + } + } else { + logg.DebugCtxf(ctx, "have challenge response", "input", input) + f.store.SetPrefix(db.DATATYPE_USERDATA) + f.store.SetSession(sessionId) + v, err := f.store.Get(ctx, []byte("challenge")) + if err != nil { + return r, err + } + h := sha256.New() + h.Write([]byte(sessionId)) + h.Write(v) + b := h.Sum(nil) + x := hex.EncodeToString(b) + if x != string(input[1:]) { + r.FlagSet = append(r.FlagSet, USER_FAILED) + r.FlagSet = append(r.FlagSet, state.FLAG_TERMINATE) + r.FlagReset = append(r.FlagReset, USER_CHALLENGED) + } else { + r.FlagSet = append(r.FlagSet, USER_SUCCEEDED) + } + } + return r, nil +} + +func main() { + var cont bool + var sessionId string + var input string + root := "root" + flag.StringVar(&sessionId, "session-id", "default", "session id") + flag.Parse() + input = flag.Arg(0) + fmt.Fprintf(os.Stderr, "starting session at symbol '%s' using resource dir: %s\n", root, scriptDir) + + ctx := context.Background() + st := state.NewState(3) + st.UseDebug() + state.FlagDebugger.Register(USER_CHALLENGED, "AUTHCHALLENGED") + state.FlagDebugger.Register(USER_FAILED, "AUTHFAILED") + state.FlagDebugger.Register(USER_SUCCEEDED, "AUTHSUCCEEDED") + store := fsdb.NewFsDb() + err := store.Connect(ctx, scriptDir) + if err != nil { + panic(err) + } + stateStore := fsdb.NewFsDb() + err = stateStore.Connect(ctx, storeDir) + if err != nil { + panic(err) + } + authStore := fsdb.NewFsDb() + err = authStore.Connect(ctx, authStoreDir) + if err != nil { + panic(err) + } + + rs := resource.NewDbResource(store) + cfg := engine.Config{ + Root: "root", + SessionId: sessionId, + } + + aux := &firstAuthResource{ + st: st, + store: authStore, + } + + pe := persist.NewPersister(stateStore) + en := engine.NewEngine(cfg, rs) + en = en.WithState(st) + en = en.WithFirst(aux.challenge) + en = en.WithPersister(pe) + err = en.AddValidInput("^%.*") + if err != nil { + fmt.Fprintf(os.Stderr, "engine inputvalid add fail: %v\n", err) + os.Exit(1) + } + + cont, err = en.Exec(ctx, []byte(input)) + if err != nil { + fmt.Fprintf(os.Stderr, "engine init pre fail: %v\n", err) + os.Exit(1) + } + if cont { + _, err = en.Exec(ctx, []byte(input)) + if err != nil { + fmt.Fprintf(os.Stderr, "engine init after fail: %v\n", err) + os.Exit(1) + } + } + + _, err = en.WriteResult(ctx, os.Stdout) + if err != nil { + fmt.Fprintf(os.Stderr, "engine finish fail: %v\n", err) + os.Exit(1) + } + + err = en.Finish() + if err != nil { + fmt.Fprintf(os.Stderr, "engine finish fail: %v\n", err) + os.Exit(1) + } +} diff --git a/examples/first/root b/examples/first/root @@ -0,0 +1 @@ +you are in! diff --git a/examples/first/root.vis b/examples/first/root.vis @@ -0,0 +1,2 @@ +CATCH foo 10 0 +HALT diff --git a/state/state.go b/state/state.go @@ -277,7 +277,8 @@ func(st *State) Down(input string) error { } if l > 0 { if st.ExecPath[l-1] == input { - panic("down into same node as previous") + s := fmt.Sprintf("down into same node as previous: %v -> '%s'", st.ExecPath, input) + panic(s) } } st.ExecPath = append(st.ExecPath, input)