1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-28 19:19:53 +00:00

Improve flychecking.

Flychecking will now work correctly with arity checking, and
will better handle imports. Well structured modules should interact
cleanly with the flychecker in a mostly safe manner, but maliciously
crafted modules can execute arbitrary code. As such, the flychecker is
not a good way to validate completely untrusted modules.

We also extend run-context with an :evaluator option to replace
:compile-only. This is more flexible and allows users to create their
own flychecker like functionality.
This commit is contained in:
Calvin Rose 2019-10-27 16:15:41 -05:00
parent d28925fdab
commit 45c2819068
3 changed files with 24 additions and 8 deletions

View File

@ -1657,7 +1657,7 @@
:env - the environment to compile against - default is the current env\n\t :env - the environment to compile against - default is the current env\n\t
:source - string path of source for better errors - default is \"<anonymous>\"\n\t :source - string path of source for better errors - default is \"<anonymous>\"\n\t
:on-compile-error - callback when compilation fails - default is bad-compile\n\t :on-compile-error - callback when compilation fails - default is bad-compile\n\t
:compile-only - only compile the source, do not execute it - default is false\n\t :evaluator - callback that executes thunks. Signature is (evaluator thunk source env where)\n\t
:on-status - callback when a value is evaluated - default is debug/stacktrace\n\t :on-status - callback when a value is evaluated - default is debug/stacktrace\n\t
:fiber-flags - what flags to wrap the compilation fiber with. Default is :ia.\n\t :fiber-flags - what flags to wrap the compilation fiber with. Default is :ia.\n\t
:expander - an optional function that is called on each top level form before being compiled." :expander - an optional function that is called on each top level form before being compiled."
@ -1669,15 +1669,15 @@
:on-compile-error on-compile-error :on-compile-error on-compile-error
:on-parse-error on-parse-error :on-parse-error on-parse-error
:fiber-flags guard :fiber-flags guard
:compile-only compile-only :evaluator evaluator
:source where :source where
:expander expand} opts) :expander expand} opts)
(default env (fiber/getenv (fiber/current))) (default env (fiber/getenv (fiber/current)))
(default chunks (fn [buf p] (getline "" buf))) (default chunks (fn [buf p] (getline "" buf)))
(default compile-only false)
(default onstatus debug/stacktrace) (default onstatus debug/stacktrace)
(default on-compile-error bad-compile) (default on-compile-error bad-compile)
(default on-parse-error bad-parse) (default on-parse-error bad-parse)
(default evaluator (fn evaluate [x &] (x)))
(default where "<anonymous>") (default where "<anonymous>")
# Are we done yet? # Are we done yet?
@ -1695,7 +1695,7 @@
(fn [] (fn []
(def res (compile source env where)) (def res (compile source env where))
(if (= (type res) :function) (if (= (type res) :function)
(unless compile-only (res)) (evaluator res source env where)
(do (do
(set good false) (set good false)
(def {:error err :line line :column column :fiber errf} res) (def {:error err :line line :column column :fiber errf} res)
@ -1890,7 +1890,8 @@
(def {:exit exit-on-error (def {:exit exit-on-error
:source source :source source
:env env :env env
:compile-only compile-only} (table ;args)) :expander expander
:evaluator evaluator} (table ;args))
(def f (if (= (type path) :core/file) (def f (if (= (type path) :core/file)
path path
(file/open path :rb))) (file/open path :rb)))
@ -1913,7 +1914,8 @@
(when (not= (fiber/status f) :dead) (when (not= (fiber/status f) :dead)
(debug/stacktrace f x) (debug/stacktrace f x)
(if exit-on-error (os/exit 1)))) (if exit-on-error (os/exit 1))))
:compile-only compile-only :evaluator evaluator
:expander expander
:source (or source (if (= f path) "<anonymous>" path))}) :source (or source (if (= f path) "<anonymous>" path))})
(when (not= f path) (file/close f)) (when (not= f path) (file/close f))
env) env)

View File

@ -454,7 +454,6 @@ static JanetSlot janetc_call(JanetFopts opts, JanetSlot *slots, JanetSlot fun) {
break; break;
case JANET_CFUNCTION: case JANET_CFUNCTION:
case JANET_ABSTRACT: case JANET_ABSTRACT:
case JANET_NIL:
break; break;
case JANET_KEYWORD: case JANET_KEYWORD:
if (min_arity == 0) { if (min_arity == 0) {

View File

@ -63,6 +63,21 @@
(def h (get handlers n)) (def h (get handlers n))
(if h (h i) (do (print "unknown flag -" n) ((get handlers "h"))))) (if h (h i) (do (print "unknown flag -" n) ((get handlers "h")))))
(def- safe-forms {'defn true 'defn- true 'defmacro true 'defmacro- true})
(def- importers {'import true 'import* true 'use true 'dofile true 'require true})
(defn- evaluator
[thunk source env where]
(if *compile-only*
(when (tuple? source)
(cond
(safe-forms (source 0)) (thunk)
(importers (source 0))
(do
(let [[l c] (tuple/sourcemap source)
newtup (tuple/setmap (tuple ;source :evaluator evaluator) l c)]
((compile newtup env where))))))
(thunk)))
# Process arguments # Process arguments
(var i 0) (var i 0)
(def lenargs (length args)) (def lenargs (length args))
@ -72,7 +87,7 @@
(+= i (dohandler (string/slice arg 1 2) i)) (+= i (dohandler (string/slice arg 1 2) i))
(do (do
(set *no-file* false) (set *no-file* false)
(dofile arg :prefix "" :exit *exit-on-error* :compile-only *compile-only*) (dofile arg :prefix "" :exit *exit-on-error* :evaluator evaluator)
(set i lenargs)))) (set i lenargs))))
(when (and (not *compile-only*) (or *should-repl* *no-file*)) (when (and (not *compile-only*) (or *should-repl* *no-file*))