Closed dubek closed 8 years ago
A sub (which is created by the evaluator) is being overwritten by temporary data of the compiler - which at that point compiles a toplevel expression (i.e. we're not inside of an eval
). This is pretty weird.
Found and fixed the problem. Will push it and describe in more detail later when I get home.
Okay, so what caused this? I found this kind of funny in a weird way:
throw()
/catch
will not change anything about call_stack_pos
. This is not a problem usually because bone_repl()
resets it to 0
when an error occured. But with _protect
, it can become a problem if we invoke the compiler (via eval
) and compilation fails. Because if it fails as it tried to access e.g. the car
of something which is not a cons cell (as it happens when compiling (if)
), this error will call backtrace()
.
Now backtrace()
did not check for silence_errors
because all the eprint
/eprintf
calls it does will do that anyway and backtrace()
is not performance critical, so it wouldn't matter if it does some unnecessary calls. However, backtrace
now iterates over the call stack, which still is in an invalid state because _protect
did not reset call_stack_pos
. The calls which used to be on the call stack are still there and the sub objects may have been overwritten - in this case, by some temporary data of the compiler.
Congratulations for finding such an obscure bug. ;-)
Example:
I couldn't reduce this code further to reliably crash. Here's the backtrace: