tomhrr / dale

Lisp-flavoured C

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add some security level (suggestion)

porky11 opened this issue · comments

This is about memory safety (similar to rust)
It should work as library without changing core language.

Additiions:
secure blocks (safe …): in such a block, only safe code is allowed to be executed
unsafe blocks (unsafe …): in safe code everything in an unsafe block is not checked for safety

How to check, if code is safe?
All forms of a secure block are checked, if they are secure.
Functions and core forms have to be declared as safe explicitely.
This may be done using a new form (safe-form name) or (def-safe-form name (macro-parameter-list))
Macros won't have to be defined as safe explicitely. They will be safe if the expansion is safe.

Functions and coreforms, that aren't safe?

  • casting
  • most extern-c functions
  • pointer-math

How should it work?
Safe will expand to a do block whose arguments will be converted to a version of the current form, but in another package, so (safe (a) b (c …) will expand to (do (safe.a) b (safe.c …))
(def-safe-form form) will be a macro too and expand to following:

(namespace safe
  (def form (macro extern (rest)
    (def namespace (var auto \ (parent-namespace mc form)))
    (def args (var auto \ (get-varargs-list mc (arg-count mc) rest)))
    (def safe-args (var auto \ (safe-list mc args))) ;;safe-list will replace all operations to safe operations
    (qq using-namespace (uq parent-name-space) (form (uql safe-args))))))

(this only is possible with #154, also to find the namespace called safe of the package. It could also implemented similar to names of concept-macros)
and is only useful with functions (in macros it normally would lead to errors).
More complex functions like this may be defined in a simple way.
(unsafe …) will print an error message and exit on error
(safe.unsafe …) will expand to (do …) without converting the arguments to safe arguments.
If the safe functions are not implemented, they will just retrun a function error, if the names are not macros, else the macro will expand the original macro but wrap the result into a safe block.
It would be easier, to defined, what is done with undefined functions when #153 would be implemented in core, but some search-and-replace macro may reimplement this behaviour, too.
(if there are other implementation strategies, I'd like to know)

Why would this be an important feature to dale?
dale is the only language I know, where it's pretty normal to get memory errors at compile time, even if there are no bugs. Especially macro expansions should be safe.
Maybe it would even be useful to only allow safe code in every macro (or even using safe by default in most cases)

I wrote some example of what I meant (see src/test.dt for some simple usage)
https://github.com/porky11/dale-secure
Some things may still not work correctly and some design decisions should be thought about.
(it also makes use of apply-list #158)