-
Notifications
You must be signed in to change notification settings - Fork 35
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
Query mode isn't enforced properly #459
Comments
I just pushed in a bunch of changes to catch more of the "bad" use cases. To summarize, consider the following 5 definitions: module Documentation.SBV.Examples.Test where
import Data.SBV
import Data.SBV.Internals
import Data.SBV.Control
test1 :: IO ThmResult
test1 = prove $ do
x <- sBool "x"
query $ pure x
test2 :: IO SatResult
test2 = sat $ do
x <- sBool "x"
query $ pure x
test3 :: IO (SBool, Result)
test3 = runSymbolic (SMTMode QueryInternal ISetup False z3) $ do
x <- sBool "x"
query $ pure x
test4 :: IO SBool
test4 = runSMT $ do
x <- sBool "x"
query $ pure x
test5 :: IO (SBool, Result)
test5 = runSymbolic (SMTMode QueryExternal ISetup False z3) $ do
x <- sBool "x"
query $ pure x Currently,
So far so good: if you use
Strictly speaking, this is OK, but is precisely exposing the very original design flaw (dating back to #71): It leaks the symbolic context out, and you can use that to do bad things. Unfortunately, there isn't much we can do here unless we go for an Finally,
What happened here is actually correct but can be confusing! The issue is that you reached out to internals, and used So, long story short, aside from the existing bug #71, I think we now properly handle and reject the scenarios that are not supported for good reasons. This is obviously a behavioral change, and I'd be interested in hearing from you that you can still write your programs with the current restrictions. (And please avoid Let me know how it goes! |
I wanted to emphasize how important it is to avoid programs like import Data.SBV
import Data.SBV.Control
import Control.Monad.Trans
leak :: IO SBool
leak = runSMT $ do x <- sBool "x"
query $ pure x
terrible :: IO ThmResult
terrible = proveWith z3{verbose=True} $ do
y <- sBool "y"
x <- lift leak -- reach in!
return $ y .== x This should be illegal! But it type checks and you get: *Main> terrible
** Calling: z3 -nw -in -smt2
[GOOD] ; Automatically generated by SBV. Do not edit.
[GOOD] (set-option :print-success true)
[GOOD] (set-option :global-declarations true)
[GOOD] (set-option :smtlib2_compliant true)
[GOOD] (set-option :diagnostic-output-channel "stdout")
[GOOD] (set-option :produce-models true)
[GOOD] (set-logic QF_BV)
[GOOD] ; --- uninterpreted sorts ---
[GOOD] ; --- tuples ---
[GOOD] ; --- sums ---
[GOOD] ; --- literal constants ---
[GOOD] ; --- skolem constants ---
[GOOD] (declare-fun s0 () Bool) ; tracks user variable "y"
[GOOD] ; --- constant tables ---
[GOOD] ; --- skolemized tables ---
[GOOD] ; --- arrays ---
[GOOD] ; --- uninterpreted constants ---
[GOOD] ; --- user given axioms ---
[GOOD] ; --- formula ---
[GOOD] (assert false)
[SEND] (check-sat)
[RECV] unsat
*** Solver : Z3
*** Exit code: ExitSuccess
Q.E.D. This is obviously unsound! Once you leak something out to If I was designing SBV today, I'd have insisted on a I'm happy to discuss this further if necessary. But here's an easy rule-of-thumb: if you have |
Hi Levent, thanks for the great explanation and work to fix this. Some other stuff came up so I didn't get to work on this as much as I had hoped to today. I believe we'll be able to rewrite our code to avoid this issue, but I'm not sure yet. I'll write back hopefully tomorrow when I know more. |
Now that I've looked at this more, I believe we have a legitimate use case that we can't implement due to the existing external query quantifier check. In our setting, we have two classes of variables and constraints:
When we set up our system of constraints we assert constraints from both of these classes simultaneously, then check for validity. When sbv finds that the combined system is invalid, we use a Importantly, we only query for the value of variables in class 2, which I believe is safe (but currently disallowed). Does this seem like a legitimate use case? And am I right this is currently impossible? If so, what's the best way to work around this? Thanks for the help. |
Absolutely legitimate use case, and admitted by SBV:
It's hard to support due to the issues listed in #407. How about the following compromise: We can add a config parameter, say Would that work for you guys? Wouldn't be too hard to implement. |
That sounds perfect 👍 |
Ok, give it a shot! Remember that you're on your own if you "breach" contract and do a {-# LANGUAGE ScopedTypeVariables #-}
import Data.SBV
import Data.SBV.Control
test1 :: IO Bool
test1 = runSMTWith z3{verbose=True,allowQuantifiedQueries=True} $ do
x :: SBool <- forall "x"
query $ do ensureSat
getValue x This produces:
Let me know how it works out and handles your actual use case. |
I can confirm your change works for us! Thanks so much for the help on this. |
Fantastic! Glad to hear. |
* We're now back on Levent's sbv (:tada:) * When SBV 8.1 is released we can switch to it to be back on a hackage release * We now add names to all allocations to make debugging much easier * The quantified variables issue that's been haunting us since forever is finally fixed (see LeventErkok/sbv#459) * We now need to add `Ord` constraints in some places due to sbv changes.
The text was updated successfully, but these errors were encountered: