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

Fix printing of arrays when they appear in counterexamples. #2110

Merged
merged 1 commit into from
Sep 5, 2024

Conversation

sauclovian-g
Copy link
Collaborator

See commit for notes. Fixes #2049.

@sauclovian-g sauclovian-g added topics: error-messages Issues involving the messages SAW produces on error needs test Issues for which we should add a regression test usability An issue that impedes efficient understanding and use tech debt Issues that document or involve technical debt topics: error-handling Issues involving the way SAW responds to an error condition labels Aug 28, 2024
@RyanGlScott
Copy link
Contributor

To respond to the four concerns you raise in your commit message:

  1. The type matching in indexToFOV in FirstOrder.hs isn't working correctly.

I presume you're referring to this comment?

-- XXX: presumably ty and ty2 should match and this should prevent the
-- need for the final error case, but I can't get it to work
indexToFOV :: BaseTypeRepr ty -> Assignment IndexLit ty2 -> Either String FirstOrderValue

If so, then I think you can (and should) make the types the same. That being, this function will still need to be partial, since IndexLit only has cases for BaseIntegerType and BaseBVType. (The fact that there aren't IndexLits for other types is a bit curious, but I don't think we need to solve that problem just yet.)

There is similar code in what4 dealing with IndexLits that is also partial (e.g., here), so would be in line with how this is handled elsewhere.

  1. Fixing FirstOrderValue arrays (FOVArray) to contain actual values changes the associated JSON schema and it's not clear what the ramifications of that are.

I think this is fine. It is not at all clear to me what the previous implementation of FOVArray was meant to do, and I think your version is a strict improvement. From that perspective, I think it's fine to update the JSON schema for FOVArrays as well. The JSON schema is (AFAIU) only used as part of SAW's caching mechanism.

  1. Fixing the conversion to Term changes the behavior of anything that exercised that code path. It's not clear what ramifications that has either, although since the prior behavior was to mysteriously generate types instead of values, it's fairly unlikely anything important depends on it.

Similarly, I have no idea what the previous code path was trying to do—it seems rather broken. I'd be much happier with something resembling the new code in this PR.

  1. Currently if we get an ArrayMapping GroundValue array (one where you can only get values out by calling a lookup function) we fail. It's not clear if these ever appear or what should actually be done if one does.

It is absolutely possible for what4 to produce an ArrayMapping value when producing a GroundArray. Here is a proof of concept:

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
module Main (main) where

import Data.Foldable (forM_)
import qualified Data.Parameterized.Context as Ctx
import Data.Parameterized.Nonce (newIONonceGenerator)
import Data.Parameterized.Some (Some(..))
import System.IO (stdout)

import What4.Config
import What4.Expr
import What4.Interface
import What4.Solver
import What4.Protocol.SMTLib2

z3executable :: FilePath
z3executable = "z3"

main :: IO ()
main = do
  Some ng <- newIONonceGenerator
  sym <- newExprBuilder FloatIEEERepr EmptyExprBuilderState ng
  extendConfig z3Options (getConfiguration sym)

  arr <-
    freshConstant
      sym
      (safeSymbol "arr")
      (BaseArrayRepr (Ctx.Empty Ctx.:> BaseIntegerRepr) BaseBoolRepr)
  idx27 <- intLit sym 27
  arr27 <- arrayLookup sym arr (Ctx.Empty Ctx.:> idx27)
  idx42 <- intLit sym 42
  arr42 <- arrayLookup sym arr (Ctx.Empty Ctx.:> idx42)
  p <- andPred sym arr27 =<< notPred sym arr42
  checkModel sym p arr
    [ ("idx27", SomeExpr idx27)
    , ("arr27", SomeExpr arr27)
    , ("idx42", SomeExpr idx42)
    , ("arr42", SomeExpr arr42)
    ]

data SomeExpr t where
  SomeExpr :: Show (GroundValue tp) => Expr t tp -> SomeExpr t

printGroundArray ::
  Show (GroundValue b) =>
  GroundArray idx b ->
  IO ()
printGroundArray gArr =
  case gArr of
    ArrayMapping{} ->
      putStrLn "ArrayMapping"
    ArrayConcrete def updates ->
      putStrLn $ showString "ArrayConcrete "
               . showsPrec 11 def
               . showChar ' '
               . showsPrec 11 updates
               $ ""

checkModel ::
  Show (GroundValue b) =>
  ExprBuilder t st fs ->
  BoolExpr t ->
  Expr t (BaseArrayType idx b) ->
  [(String, SomeExpr t)] ->
  IO ()
checkModel sym f arr es = do
  withZ3 sym z3executable defaultLogData $ \session -> do
    assume (sessionWriter session) f
    runCheckSat session $ \result ->
      case result of
        Sat (ge, _) -> do
          putStrLn "Satisfiable, with model:"
          gArr <- groundEval ge arr
          printGroundArray gArr
          forM_ es $ \(nm, SomeExpr e) -> do
            v <- groundEval ge e
            putStrLn $ "  " ++ nm ++ " := " ++ show v
        Unsat _ -> putStrLn "Unsatisfiable."
        Unknown -> putStrLn "Solver failed to find a solution."

Running this yields:

Satisfiable, with model:
ArrayMapping
  idx27 := 27
  arr27 := True
  idx42 := 42
  arr42 := False

That being said, I don't have a clear idea of how we'd represent ArrayMapping values in SAWCore. I think it would be fine to fail for now if we encounter one.

@sauclovian-g
Copy link
Collaborator Author

  1. Got it fixed, thanks (for anyone following along, part of this happened elsewhere)
  2. Ok, let's just move ahead then.
  3. Same
  4. That is what it'll do now, so I guess we can proceed... though this should probably not be merged until the current release goes out, just in case.

@sauclovian-g
Copy link
Collaborator Author

I force-pushed to squash the fix commit. This can be reviewed now, though it shouldn't be merged until the release goes out.

@sauclovian-g sauclovian-g marked this pull request as ready for review August 28, 2024 20:03
Copy link
Contributor

@RyanGlScott RyanGlScott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fantastic. Thanks, @sauclovian-g!

Also, I'll be That Guy: please make sure to mention these changes in the changelog.

saw-core/src/Verifier/SAW/FiniteValue.hs Show resolved Hide resolved
saw-core/src/Verifier/SAW/FiniteValue.hs Outdated Show resolved Hide resolved
saw-core/src/Verifier/SAW/FiniteValue.hs Outdated Show resolved Hide resolved
saw-core/src/Verifier/SAW/FiniteValue.hs Show resolved Hide resolved
saw-core/src/Verifier/SAW/FiniteValue.hs Outdated Show resolved Hide resolved
saw-core/src/Verifier/SAW/FiniteValue.hs Outdated Show resolved Hide resolved
@sauclovian-g
Copy link
Collaborator Author

(also I think all the commits should get squashed before being merged; let me know if you disagree)

CHANGES.md Outdated Show resolved Hide resolved
@sauclovian-g sauclovian-g force-pushed the 2049-print-arrays branch 2 times, most recently from 928c093 to 19e4918 Compare September 4, 2024 04:47
@sauclovian-g
Copy link
Collaborator Author

First force was to rebase on head, second to squash it all together. This should be ready to go unless it randomly explodes in the CI.

@sauclovian-g
Copy link
Collaborator Author

hmm, I tagged this "needs test" and then didn't write a test, guess I should do that

CHANGES.md Outdated Show resolved Hide resolved
intTests/test2049/Makefile Outdated Show resolved Hide resolved
- make room for values in FirstOrderValue arrays
- fix the printer functions accordingly
- we now need From/ToJSONKey instances for FirstOrderValue
- this requires Ord for FirstOrderValue and FirstOrderType
- fix the conversion of FirstOrderValue arrays to Term
- convert GroundValue array values to FirstOrderValue array values

There are three things to be aware of in case they come back to
haunt us:

- Fixing FirstOrderValue arrays (FOVArray) to contain actual values
changes the associated JSON schema. We think this only affects the
solver caching mechanism, so there's some possibility that users will
have to flush/regenerate their caches. More likely nobody will have
exercised this path, since it after all doesn't actually work; any
such current cache entries don't contain the array contents.

- Fixing the conversion to Term changes the behavior of anything that
exercised that code path. This is also probably nothing of
significance; since the the prior behavior was to mysteriously
generate types instead of values, which could hardly fail to go off
the rails downstream, it's fairly unlikely anything important depends
on it.

- Currently if we get an ArrayMapping GroundValue array (one where you
can only get values out by calling a lookup function) we fail. It's
not clear if these ever appear in practice or what should actually be
done if one does. This is a more significant possibility, though,
because the behavior now is to fail and that impacts not only the
marginal code paths described above but also the printing of
counterexamples. So we might need to add more support in the future.

This change adds indexed-traversable to saw-core and saw-core-what4,
but the rest of saw already depends on it so this has no real effect.

It also adds a test case. I've noted the provenance of the included
LLVM byte-code blob as per saw-script #1157.
@sauclovian-g
Copy link
Collaborator Author

I have squashed it again and I'll merge it after I make lunch unless it blows up for some reason.

@sauclovian-g sauclovian-g merged commit 04639d3 into master Sep 5, 2024
34 checks passed
@sauclovian-g sauclovian-g deleted the 2049-print-arrays branch September 5, 2024 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs test Issues for which we should add a regression test tech debt Issues that document or involve technical debt topics: error-handling Issues involving the way SAW responds to an error condition topics: error-messages Issues involving the messages SAW produces on error usability An issue that impedes efficient understanding and use
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Print SMT array counterexamples more intelligibly
2 participants