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

copilot-theorem: kind2Prover gives parse error when disproving a property #495

Closed
RyanGlScott opened this issue Jan 12, 2024 · 10 comments · Fixed by #510
Closed

copilot-theorem: kind2Prover gives parse error when disproving a property #495

RyanGlScott opened this issue Jan 12, 2024 · 10 comments · Fixed by #510
Assignees
Labels
CR:Status:Closed Admin only: Change request that has been completed CR:Type:Bug Admin only: Change request pertaining to error detected
Milestone

Comments

@RyanGlScott
Copy link
Contributor

(In order to reproduce this bug, you'll need to install Kind2-0.7.2, which is (as far as I can tell) the latest version of Kind2 that copilot-theorem currently supports. Note that Kind2-0.7.2 doesn't offer binary distributions, so you'll have to build it from source.)

copilot-theorem's kind2Prover is able to prove properties that are true. For instance, running this program:

module Main (main) where

import Data.Functor

import Copilot.Theorem.Kind2
import Copilot.Theorem.Prove
import Language.Copilot

spec :: Spec
spec =
  void $ theorem "true" (forAll true) (check (kind2Prover def))

main :: IO ()
main = void $ reify spec

Will yield:

(define-pred top
  ((prop-true.out Bool))
  (init
    (= prop-true.out true))
  (trans
    (= (prime prop-true.out) true)))

(check-prop
  ((true prop-true.out)))
true: valid ()
Finished: true: proof checked successfully

On the other hand, if kind2Prover attempts to disprove a property that is false, then it will crash with a parse error. This can be seen when running this program:

module Main (main) where

import Data.Functor

import Copilot.Theorem.Kind2
import Copilot.Theorem.Prove
import Language.Copilot

spec :: Spec
spec =
  void $ theorem "false" (forAll false) (check (kind2Prover def))

main :: IO ()
main = void $ reify spec
(define-pred top
  ((prop-false.out Bool))
  (init
    (= prop-false.out false))
  (trans
    (= (prime prop-false.out) false)))

(check-prop
  ((false prop-false.out)))
Main.hs: Parse error while reading the Kind2 XML output : 
Unrecognized status : falsifiable

<?xml version="1.0"?>
<Results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Log class="info" source="parser">kind2 v0.7.2</Log>
<Property name="false">
  <Runtime unit="sec" timeout="false">0.135</Runtime>
  <K>1</K>
  <Answer source="bmc">falsifiable</Answer>
  <Counterexample></Counterexample>
</Property>

</Results>

CallStack (from HasCallStack):
  error, called at src/Copilot/Theorem/Misc/Error.hs:32:9 in copilot-theorem-3.18.1-inplace:Copilot.Theorem.Misc.Error

The problem lies in this code:

parseOutput prop xml = fromJust $ do
root <- parseXMLDoc xml
case findAnswer . findPropTag $ root of
"valid" -> return (Output Valid [])
"invalid" -> return (Output Invalid [])
s -> err $ "Unrecognized status : " ++ s

This expects Kind2's XML output to have an <Answer>...</Answer> tag whose content is the string invalid. As can be seen in the XML output that is dumped in the error message above, however, the actual content of the <Answer> tag is falsifiable.

Resolving this issue would be helpful in an eventual resolution for #254. In order to check an existentially quantified property with Kind2, it would be convenient to take a universally quantified property and negate it, checking if Kind2 returns falsifiable as the answer. This won't be possible unless we first fix this issue.

@RyanGlScott
Copy link
Contributor Author

The following Dockerfile checks that theorem correctly reports that a property is unsatisfiable using the Kind2 backend:

--- Dockerfile
FROM ubuntu:focal

RUN apt-get update

RUN apt-get install --yes software-properties-common
RUN add-apt-repository ppa:hvr/ghc
RUN apt-get update

RUN apt-get install --yes \
  ghc-8.6.5 cabal-install-2.4 \
  libtool-bin libz-dev libzmq5 opam z3

# Install Kind2's OCaml dependencies
RUN opam init --auto-setup --yes --bare --disable-sandboxing \
 && opam switch create default 4.01.0 \
 && opam install -y -j "$(nproc)" camlp4 menhir \
 && opam clean -a -c -s --logs

# Install Kind2-0.7.2
ENV KIND2_VER="0.7.2"
RUN wget https://github.com/kind2-mc/kind2/archive/refs/tags/v${KIND2_VER}.zip \
 && unzip v${KIND2_VER}.zip
WORKDIR kind2-${KIND2_VER}
RUN sed -i.bak -e 's/-pedantic -Werror -Wall/-pedantic -Wall/' ocamlczmq/czmq/configure.ac
RUN eval $(opam env) \
 && ./autogen.sh \
 && ./build.sh \
 && make install
WORKDIR /

# Install GHC and Cabal
ENV PATH=/opt/ghc/8.6.5/bin:/opt/cabal/2.4/bin:$PWD/.cabal-sandbox/bin:$PATH

RUN cabal update
RUN cabal v1-sandbox init
RUN apt-get install --yes git

ADD Spec.hs /tmp/Spec.hs

SHELL ["/bin/bash", "-c"]
CMD git clone $REPO && cd $NAME && git checkout $COMMIT && cd .. \
  && cabal v1-install alex happy \
  && cabal v1-install $NAME/copilot**/ \
  && (cabal v1-exec -- runhaskell /tmp/Spec.hs | grep "false: proof failed") \
  && echo "Success"

--- Spec.hs
module Main (main) where

import Data.Functor

import Copilot.Theorem.Kind2
import Copilot.Theorem.Prove
import Language.Copilot

spec :: Spec
spec =
  void $ theorem "false" (forAll false) (check (kind2Prover def))

main :: IO ()
main = void $ reify spec

Run the Dockerfile like so:

$ docker run -e "REPO=https://github.com/Copilot-Language/copilot" -e "NAME=copilot" -e "COMMIT=f8239019b9c83315a78e2a92221b862945aa3b7c" -it copilot-theorem-495

This fails as of commit f823901:

Spec.hs: Parse error while reading the Kind2 XML output : 
Unrecognized status : falsifiable

<?xml version="1.0"?>
<Results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Log class="info" source="parser">kind2 v0.7.2</Log>
<Property name="false">
  <Runtime unit="sec" timeout="false">0.122</Runtime>
  <K>1</K>
  <Answer source="bmc">falsifiable</Answer>
  <Counterexample></Counterexample>
</Property>

</Results>

CallStack (from HasCallStack):
  error, called at src/Copilot/Theorem/Misc/Error.hs:32:9 in copilot-theorem-3.19-CUYLKPoYpZX7ZyknpdGomd:Copilot.Theorem.Misc.Error```

@ivanperez-keera
Copy link
Member

Thank you, @RyanGlScott .

@ivanperez-keera
Copy link
Member

ivanperez-keera commented Apr 24, 2024

Description

copilot-theorem crashes when trying to disprove a property that is false using kind2Prover.

kind2Prover expects the word used in kind2's XML output to be invalid, but the keyword used is falsifiable, leading to a parse error.

Type

  • Bug: crash when passing valid input to function.

Additional context

None.

Requester

  • Ryan Scott (Galois)

Method to check presence of bug

Attempting to run the following spec with kind2-0.7.2:

module Main (main) where

import Data.Functor

import Copilot.Theorem.Kind2
import Copilot.Theorem.Prove
import Language.Copilot

spec :: Spec
spec =
  void $ theorem "false" (forAll false) (check (kind2Prover def))

main :: IO ()
main = void $ reify spec

leads to a crash due to a parse error:

Spec.hs: Parse error while reading the Kind2 XML output : 
Unrecognized status : falsifiable

<?xml version="1.0"?>
<Results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Log class="info" source="parser">kind2 v0.7.2</Log>
<Property name="false">
  <Runtime unit="sec" timeout="false">0.122</Runtime>
  <K>1</K>
  <Answer source="bmc">falsifiable</Answer>
  <Counterexample></Counterexample>
</Property>

</Results>

CallStack (from HasCallStack):
  error, called at src/Copilot/Theorem/Misc/Error.hs:32:9 in copilot-theorem-3.19-CUYLKPoYpZX7ZyknpdGomd:Copilot.Theorem.Misc.Error

Expected result

Running the spec above should complete correctly, and produce an output that contains the text "false: proof failed", since the property we are attempting to prove is falsifiable.

Desired result

Running the spec above should complete correctly, and produce an output that contains the text "false: proof failed", since the property we are attempting to prove is falsifiable.

Proposed solution

Modify copilot-theorem:Copilot.Theorem.Kind2.Output.parseOutput to expect the word falsifiable, rather than invalid.

Further notes

None.

@ivanperez-keera ivanperez-keera added CR:Type:Bug Admin only: Change request pertaining to error detected CR:Status:Initiated Admin only: Change request that has been initiated labels Apr 24, 2024
@ivanperez-keera
Copy link
Member

Change Manager: Confirmed that the bug exists.

@ivanperez-keera ivanperez-keera added CR:Status:Confirmed Admin only: Change request that has been acknowledged by the change manager and removed CR:Status:Initiated Admin only: Change request that has been initiated labels Apr 24, 2024
@ivanperez-keera
Copy link
Member

Technical Lead: Confirmed that the issue should be addressed.

@ivanperez-keera ivanperez-keera added CR:Status:Accepted Admin only: Change request accepted by technical lead and removed CR:Status:Confirmed Admin only: Change request that has been acknowledged by the change manager labels Apr 24, 2024
@ivanperez-keera
Copy link
Member

Technical Lead: Issue scheduled for fixing in Copilot 3.20.

Fix assigned to: @RyanGlScott .

@ivanperez-keera ivanperez-keera added CR:Status:Scheduled Admin only: Change requested scheduled and removed CR:Status:Accepted Admin only: Change request accepted by technical lead labels Apr 24, 2024
@ivanperez-keera ivanperez-keera added this to the 3.20 milestone Apr 24, 2024
RyanGlScott added a commit to GaloisInc/copilot-1 that referenced this issue Apr 24, 2024
…Language#495.

Currently, the TransSys code that `copilot-theorem`'s Kind2 backend generates
is only accepted by Kind-0.7.2. This patch makes this version requirement more
obvious in the `copilot-theorem` `README`.
RyanGlScott added a commit to GaloisInc/copilot-1 that referenced this issue Apr 24, 2024
…-Language#495.

In Kind2-0.7.2, disproven properties are tagged with `falsifiable` in the XML
output, but the code in `copilot-theorem`'s Kind2 backend was instead searching
for a tag named `invalid`. As a result, `copilot-theorem` would error when
attempting to disprove properties that are false, as it fail to parse the XML
output. This fixes the issue by replacing `invalid` with `falsifiable`.
RyanGlScott added a commit to GaloisInc/copilot-1 that referenced this issue Apr 24, 2024
@RyanGlScott
Copy link
Contributor Author

Implementor: Solution implemented, review requested.

@agoodloe
Copy link
Member

agoodloe commented Apr 24, 2024 via email

@ivanperez-keera ivanperez-keera added CR:Status:Implementation Admin only: Change request that is currently being implemented and removed CR:Status:Scheduled Admin only: Change requested scheduled labels Apr 25, 2024
@ivanperez-keera ivanperez-keera added CR:Status:Verification Admin only: Change request that is currently being verified and removed CR:Status:Implementation Admin only: Change request that is currently being implemented labels May 5, 2024
RyanGlScott added a commit to GaloisInc/copilot-1 that referenced this issue May 5, 2024
…-Language#495.

In Kind2, disproven properties are tagged with `falsifiable` in the XML output,
but the code in `copilot-theorem`'s Kind2 backend was instead searching for a
tag named `invalid`. As a result, `copilot-theorem` would error when attempting
to disprove properties that are false, as it fail to parse the XML output. This
fixes the issue by replacing `invalid` with `falsifiable`.
RyanGlScott added a commit to GaloisInc/copilot-1 that referenced this issue May 5, 2024
@ivanperez-keera
Copy link
Member

Change Manager: Verified that:

  • Solution is implemented:
      --- Dockerfile
      FROM ubuntu:focal
      
      RUN apt-get update
      
      RUN apt-get install --yes software-properties-common
      RUN add-apt-repository ppa:hvr/ghc
      RUN apt-get update
      
      RUN apt-get install --yes \
        ghc-8.6.5 cabal-install-2.4 \
        libtool-bin libz-dev libzmq5 opam z3
      
      # Install Kind2's OCaml dependencies
      RUN opam init --auto-setup --yes --bare --disable-sandboxing \
       && opam switch create default 4.01.0 \
       && opam install -y -j "$(nproc)" camlp4 menhir \
       && opam clean -a -c -s --logs
      
      # Install Kind2-0.7.2
      ENV KIND2_VER="0.7.2"
      RUN wget https://github.com/kind2-mc/kind2/archive/refs/tags/v${KIND2_VER}.zip \
       && unzip v${KIND2_VER}.zip
      WORKDIR kind2-${KIND2_VER}
      RUN sed -i.bak -e 's/-pedantic -Werror -Wall/-pedantic -Wall/' ocamlczmq/czmq/configure.ac
      RUN eval $(opam env) \
       && ./autogen.sh \
       && ./build.sh \
       && make install
      WORKDIR /
      
      # Install GHC and Cabal
      ENV PATH=/opt/ghc/8.6.5/bin:/opt/cabal/2.4/bin:$PWD/.cabal-sandbox/bin:$PATH
      
      RUN cabal update
      RUN cabal v1-sandbox init
      RUN apt-get install --yes git
      
      ADD Spec.hs /tmp/Spec.hs
      
      SHELL ["/bin/bash", "-c"]
      CMD git clone $REPO && cd $NAME && git checkout $COMMIT && cd .. \
        && cabal v1-install alex happy \
        && cabal v1-install $NAME/copilot**/ \
        && (cabal v1-exec -- runhaskell /tmp/Spec.hs | grep "false: proof failed") \
        && echo "Success"
    
      --- Spec.hs
      module Main (main) where
      
      import Data.Functor
      
      import Copilot.Theorem.Kind2
      import Copilot.Theorem.Prove
      import Language.Copilot
      
      spec :: Spec
      spec =
        void $ theorem "false" (forAll false) (check (kind2Prover def))
      
      main :: IO ()
      main = void $ reify spec
    Command (substitute variables based on new path after merge):
    $ docker run -e "REPO=https://github.com/GaloisInc/copilot-1" -e "NAME=copilot-1" -e "COMMIT=b153fbc2231ad33862d2b7a94986f0a90bf501f9" -it copilot-verify-495
    
  • Implementation is documented. Details:
    No updates needed.
  • Change history is clear.
  • Commit messages are clear.
  • Changelogs are updated.
  • Examples are updated. Details:
    No updates needed.
  • Required version bumps are evaluated. Details:
    Bump not needed (bug fix).

@ivanperez-keera
Copy link
Member

Change Manager: Implementation ready to be merged.

@ivanperez-keera ivanperez-keera added CR:Status:Closed Admin only: Change request that has been completed and removed CR:Status:Verification Admin only: Change request that is currently being verified labels May 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CR:Status:Closed Admin only: Change request that has been completed CR:Type:Bug Admin only: Change request pertaining to error detected
Development

Successfully merging a pull request may close this issue.

3 participants