Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any kind of run-time exception causes the REPL to exit #814

Closed
brianhuffman opened this issue Aug 12, 2020 · 4 comments · Fixed by #954
Closed

Any kind of run-time exception causes the REPL to exit #814

brianhuffman opened this issue Aug 12, 2020 · 4 comments · Fixed by #954
Assignees

Comments

@brianhuffman
Copy link
Contributor

If the argument to eval_size (which is a saw-script value of type Type) does not evaluate to a finite numeric type, then it crashes the REPL:

sawscript> eval_size {| 3 + 4 |}
[23:19:59.422] 7
sawscript> eval_size {| inf |}
saw: Stack trace:
"eval_size" (<stdin>:1:1-1:10):
eval_size: illegal infinite size
sawscript> eval_size {| [8] |}
saw: Stack trace:
"eval_size" (<stdin>:1:1-1:10):
eval_size: not a numeric type

We should make it throw a catchable run-time error, so the REPL can handle it more gracefully.

@brianhuffman
Copy link
Contributor Author

It looks like eval_bool, eval_int, and eval_list will similarly crash the REPL:

sawscript> eval_bool {{ 5 : Integer }}
saw: Stack trace:
"eval_bool" (<stdin>:1:1-1:10):
eval_bool: not type Bit
sawscript> eval_int {{ True }}
saw: Stack trace:
"eval_int" (<stdin>:1:1-1:9):
eval_int: argument is not a finite bitvector
sawscript> eval_list {{ 5 : Integer }}
saw: Stack trace:
"eval_list" (<stdin>:1:1-1:10):
eval_list: not a monomorphic array type

We should fix all of these.

@brianhuffman
Copy link
Contributor Author

It looks like the problem is much more general than I had realized. As it turns out, any failing computation in saw-script will cause the REPL to exit. For example, division by 0:

sawscript> print {{ 0x00 / 0x00 }}
saw: division by 0

The fails combinator can successfully prevent the REPL from exiting in some cases. However it takes some trickery to get fails to catch errors arising from functions with non-monadic saw-script types:

// This is a workaround to delay evaluation of a pure function
// so that `fails` can catch any errors raised.
let apply f x = do { () <- return (); return (f x); };

Any REPL command that causes the kind of failure that can be caught by fails should cause the REPL to print the error message, and then return to another REPL prompt; it should not exit the program.

@brianhuffman
Copy link
Contributor Author

I found a nice easy example to test the REPL error handling: the fails combinator itself. When given a computation that succeeds (e.g. return true), the Haskell implementation of fails calls fail in the IO monad, which raises an IO exception. Wrapping it in another fails can catch it just fine.

sawscript> fails (fails (return true))
== Anticipated failure message ==
Stack trace:
"fails" (<stdin>:1:8-1:13):
Expected failure, but succeeded instead!
sawscript> fails (return true)
saw: Stack trace:
"fails" (<stdin>:1:1-1:6):
Expected failure, but succeeded instead!

In recent versions of saw, the last command fails (return true) will exit the REPL. But it didn't always do that; versions of saw from the beginning of the year stay in the REPL.

So I did a git bisect, which revealed that 7dab9d5 is the first bad commit.

commit 7dab9d59dd30dbe253cf0b51f9af9ba18c5d3798
Author: Samuel Breese <[email protected]>
Date:   Wed Apr 22 14:35:18 2020 -0400

    Fix stack traces, properly catch fails from Crucible

@brianhuffman
Copy link
Contributor Author

The saw-script stack-trace mechanism works by putting an exception handler around every function call: Each handler catches an IO exception, then throws a new one with some additional location information attached to it.

Before 7dab9d5, it would always rethrow an IOError.userError (which is the same kind of exception produced by fail in the IO monad). But starting with 7dab9d5, it now throws an SS.TraceException instead. I suspect that the REPL exception handler is only able to catch the userError exceptions, and that the SS.TraceException ones are not caught and cause the REPL to exit.

@brianhuffman brianhuffman changed the title eval_size crashes on inf or non-numeric types Any kind of run-time exception causes the REPL to exit Dec 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants