Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix backtracking on the topmost predicate triggering UB in run_module…
…_predicate Fixes #2815, see that issue for my investigation. This is a one-line fix that I'm quite proud of :) If the topmost query for `run_module_predicate` needs to backtrack, then before this commit, one of the following two things may happen: - A dangling OrFrame is read at stack offset 0 - An AndFrame was at stack offset 0 would be read as an OrFrame This can be seen by either calling `run_module_predicate` with a throwing predicate (encountering the second scenario) or a failing predicate (encountering the first scenario), or by running the following in the REPL, which triggers a `throw/1` within the error handler, propagating it all the way up (and encountering the second scenario): ```prolog ?- current_output(S), open(stream(S), write, S0, [type(binary)]). ``` Currently, `Stack` is not equipped with tools to detect this incorrect behavior, so it would instead try to read an OrFrame at offset 0, which triggers UB, since transmuting between AndFramePrelude and OrFramePrelude isn't legal. In practice, since `AndFramePrelude` is smaller, the later fields of `OrFramePrelude` would read from the cells following the `AndFramePrelude`, and would contain nonsensical data, triggering the panic that led to my investigation in #2815 and that is fairly reliable to witness. Surprisingly, this wouldn't happen with `run_query`, which led me to look at how they operate differently. It turns out that `run_query` inserts an OrFrame at offset 0, which covers both problematic scenarios. The fix is thus to simply add a call to `Machine::allocate_stub_choice_point` in `run_module_predicate` :)
- Loading branch information