waforth icon indicating copy to clipboard operation
waforth copied to clipboard

CPU Metering / Reduction Counts

Open RickCarlino opened this issue 2 years ago • 2 comments

Hi again,

I have been exploring the possibility of WAForth as a lighter-weight alternative to Lua as a plugin environment or a language that can be embedded into a larger one. One challenge that comes up is the fact that a poorly/maliciously written Forth script could block the JS event loop and make the application unresponsive by way of an endless loop. I've also noticed that some error conditions can cause this also. I hit this issue earlier today, but unfortunately, did not have time to file a proper bug report- sorry! Will take better notes if it happens again.

I have seen that some WASM runtimes like Wasmer appear to support a "gas metering" concept that prevents overconsumption of CPU resources.

Are there any ways to accomplish CPU rationing with WAForth as it currently exists?

RickCarlino avatar May 19 '22 01:05 RickCarlino

A Forth where you can trust any program to be executed to not do anything wrong? Interesting concept 😅

The WASM-level gas metering concept is interesting, but indeed very specific to the implementation.

Here are some thoughts on your second alternative (I may come back to edit this and add things as I think of them):

  • To avoid long and infinite loops, there would have to be a regular check to see if some condition has been met.
    • For user words, this is probably easily done by adding something to the compilation of word calls. You could keep some global variable that is checked and incremented on each word call. Given the overhead of indirect word calls, I'd assume this isn't too bad performance-wise (if you have a fast mutable global var implementation). The same increment+check probably needs to be done when emitting control flow instructions too (as these don't rely on word calls). The complexity here is probably manageable (and can be easily stripped using a WAForth patch script)
    • For core words, this is annoying, because it adds complexity to (and slows down) the core, as you would need to start sprinkling checks all over the code. I'd rather investigate that it can be ensured core words cannot go into infinite / long loops. E.g., a user can make FIND et al. loop by writing pointers into the dictionary that make the lookup loop; this particular case can be avoided by checking that dictionary lookup is done in descending address order, and a bound check. However, I'm not sure if this can be guaranteed for all words from the top of my head: every loop instruction in the core would have to be investigated.
  • Everything in data memory is modifiable by user code, which means a lot of the execution of words can be influenced. However, code does not reside in data memory, so it's good that code can't be modified. WAForth also doesn't use the return stack for control flow, so control flow cannot be influenced either.
  • The code template for compiling WASM words can be modified, and can result in infinite loops. It would be handy if this could be put in read-only memory, not sure if WebAssembly multiple memory spec allows this
  • Random jumps in general are not possible (in WebAssembly by design), so nothing can go wrong there either

remko avatar May 19 '22 16:05 remko

A Forth where you can trust any program to be executed to not do anything wrong? Interesting concept 😅

If you look at it that way, I guess this is a strange request😅 I will take a deeper look at the code and think it over more. Thanks for the pointers!

RickCarlino avatar May 21 '22 13:05 RickCarlino

Closing it for now. If more information should emerge, feel free to share.

remko avatar Feb 24 '24 09:02 remko