willner@cfa.harvard.EDU (Steve Willner) (07/22/87)
In article <sUzP8Vy00Us=wNM0-x@andrew.cmu.edu>, lord+@andrew.cmu.edu (Tom Lord) writes: > 2) What work has been done on `crash proof' forth systems? At what cost to > execution speed? Magic/L is a forth-like language with memory management that should make it nearly crash-proof. But I've never used it myself, so don't know how it actually works out in practice. The vendor is Loki Engineering, 55 Wheeler St., Cambridge, MA 02138, phone 617-576-0666. I believe they have a Unix-compatible version of some sort, but you should contact them for more information. A forth _application_ (as distinct from a _system_) can be essentially crash-proof if the programmer does a good job. I'd suggest four areas for attention. None of these compromises execution speed within the program. 1) The main thing is to prevent storing garbage in unfortunate locations (like the dictionary). At a minimum, write extra words so that users never have to use "!" directly. If you want to be even more careful, you can end your program by redefining "!" and related words so certain parts of memory cannot be changed. In practice, I have not found this extreme to be necessary. 2) The second most important thing is to make unavailable any words that are dangerous (e.g. words that should only be called after something else has happened.) A variety of techniques can be used, depending on the system. At a minimum, give dangerous words names that are not likely to be typed by accident. Most systems have a smudge bit or some way of (reversibly) making words unrecognizable; use it to prevent a user from accessing dangerous words. An easy alternative is to redefine dangerous words after your program has used them for the last time so the new word just gives an error message. My own technique is to name dangerous words in lower case and to set the system bit that converts terminal input to upper case. (Telling users to always set the "caps lock" on the terminal would be just as effective but would prevent users from typing readable text.) Or if you're really paranoid, write a parser that only recognizes and executes selected, safe words and does so only after checking that all arguments (on stack or elsewhere) are appropriate. 3) Limit the damage. If "@", "!", or any other words don't check the stack before or after every execution, redefine them at the end of the application code so they do. That way a user-written routine that makes a stack error will abort immediately rather than calling more words with wrong values on the stack. 4) For a multitasking system, make sure users can't do something that hogs the CPU. Our system, for example, can only switch processes when it encounters a ";", and all long loops must therefore contain at least one colon-word so the process can be suspended. The solution is to make sure that all loops defined within the application contain a colon-word, and at the end redefine "DO", "BEGIN", etc. so they always compile "DUM" (a no-op colon word) within any loop a user might execute. These suggestions are not perfect protection, but as a practical matter they have worked very well in preventing crashes caused by careless users. Now if only I could figure out how to prevent crashes from broken hardware and from bad programs :-) -- Steve Willner Phone 617-495-7123 Bitnet: willner@cfa1 60 Garden St. FTS: 830-7123 UUCP: willner@cfa Cambridge, MA 02138 USA Telex: 921428 satellite cam
mj@myrias.UUCP (Michal Jaegermann) (07/23/87)
To all fine advice how to make Forth *application* crash-proof one may add the following: Strip headers from all words but user interface. You will save a lot of memeory, which now is wasted, and nobody will find anything which s/he is not supposed to see :-).. Michal Jaegermann Myrias Research Corporation ...ihnp4!alberta!myrias!mj
andrew@teletron.UUCP (Andrew Scott) (07/24/87)
In article <629@cfa.cfa.harvard.EDU>, willner@cfa.harvard.EDU (Steve Willner) writes: > > 4) For a multitasking system, make sure users can't do something that > hogs the CPU. Our system, for example, can only switch processes > when it encounters a ";", and all long loops must therefore contain > at least one colon-word so the process can be suspended. The > solution is to make sure that all loops defined within the > application contain a colon-word, and at the end redefine "DO", > "BEGIN", etc. so they always compile "DUM" (a no-op colon word) > within any loop a user might execute. Another technique is to allow the system to switch processes during the call to NEXT at the end of every primitive. This works especially well if NEXT is implemented as an indirect jump through an address register - just patch the register value to point to the context switching code and restore it for the next process. Then, the only restriction is to forbid primitives to use up a lot of CPU time. Also, any shared resource used by multiple processes may be accessed from within a primitve without having to use any kind of semaphores. These techniques assume that there is some kind of process scheduler. Many FORTH multitasking systems (especially process control type systems) use cooperative multitasking schemes. That is, it is up to each process to relenquish CPU control during long loops etc. This reduces quite a bit of overhead. Note that *multiuser* systems should still have some kind of scheduler to guard against runaway processes. Andrew