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

Nested calls to prove is unsound, and are thus rejected #71

Closed
LeventErkok opened this issue Jun 4, 2013 · 0 comments
Closed

Nested calls to prove is unsound, and are thus rejected #71

LeventErkok opened this issue Jun 4, 2013 · 0 comments
Assignees
Labels

Comments

@LeventErkok
Copy link
Owner

LeventErkok commented Jun 4, 2013

From a programmability perspective, it's nice to be able to embed arbitrary IO actions into a symbolic computation, and SBV allows this via the usual call to liftIO. But this is unsound if that IO action happens to create symbolic variables itself, which then gets conflated with the calling context. SBV has a dynamic check to reject such scenarios, where you'll get an error of the form:

*** Exception: Data.SBV: Mismatched contexts detected.
***
*** Current context: SBVContext 1220800691632037763
*** Mixed with     : SBVContext (-5269368573634985637)
***
*** This happens if you call a proof-function (prove/sat) etc.
*** while another one is in execution. Avoid such nested calls.
*** See https://github.com/LeventErkok/sbv/issues/71 for examples.

It would be nice if this was caught as a type-error: Alas the design for that requires a complete rewrite of how the Symbolic monad works, similar to how runST operates. Unfortunately, this is not feasible for the time being, due to backwards-compatibility concerns and making the types involved even more complicated. So, we catch such uses dynamically and error out as an "acceptable crutch."

If you run into the above message, see if your use is similar to the examples below. In general, you should never make a call to prove/sat etc. while running another SBV call. The typical case for this is the incremental use of solvers, and for that you should use the query-mode of SBV, which handles such interactions in a safe way.

Here's a few examples to demonstrate the kinds of problems that cause this issue:

{-# OPTIONS_GHC -Wall -Werror #-}

import Data.SBV
import Data.SBV.Control
import Control.Monad.Trans

bug1 :: IO ThmResult
bug1 = proveWith z3{verbose=True} $ do
  x <- free "x"
  y <- free "y"
  liftIO $ f x y
 where f :: SWord32 -> SWord32 -> IO SBool
       f x y = do
         res <- isSatisfiableWith z3{verbose=True} $ x .== y
         return $ if res then sTrue else sFalse

bug2 :: IO ThmResult
bug2 = proveWith z3{verbose=True} $ do
  x <- free "x"
  liftIO $ f x
 where f :: SWord32 -> IO SBool
       f x = do
         res <- isSatisfiableWith z3{verbose=True} $ x .== 2
         return $ if res then sTrue else sFalse

bug3 :: IO ThmResult
bug3 = proveWith z3{verbose=True} $ do
        y <- sBool "y"
        x <- lift leak        -- reach in!
        return $ y .== x
  where leak :: IO SBool
        leak = runSMTWith z3{verbose=True} $ do
                        x <- sBool "x"
                        query $ pure x

All of these behave in bad ways, compromising soundness. Thus SBV catches them at run-time and flags such uses as an error.

@LeventErkok LeventErkok self-assigned this Apr 29, 2015
@LeventErkok LeventErkok changed the title Keep track of internal contexts Arbitrary embedding of IO actions into Symbolic is unsound Nov 25, 2023
@LeventErkok LeventErkok changed the title Arbitrary embedding of IO actions into Symbolic is unsound Nested calls to prove is unsound, and rejected Nov 27, 2023
@LeventErkok LeventErkok changed the title Nested calls to prove is unsound, and rejected Nested calls to prove is unsound, and are thus rejected Nov 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant