angr/claripy

Solver.is_true and is_false providing inconsistent behavior

Closed this issue · 2 comments

When using a solver to evaluate boolean expressions, I get different results when using the is_true and is_false functions than I do when using eval. The docs for is_true and is_false state that they may be incorrect if the expression has been simplified by z3, but the following example is extremely simple and I would not expect it to be simplified:

In [1]: import claripy

In [2]: s = claripy.Solver()

In [3]: x = claripy.BVS("x",32)

In [4]: s.add(x==4)
Out[4]: (<Bool x_0_32 == 0x4>,)

In [5]: s.is_true(x==4)
Out[5]: False

In [6]: s.is_false(x!=4)
Out[6]: False

In [7]: s.is_false(x==4)
Out[7]: False

In [8]: s.eval(x==4,1)
Out[8]: (True,)

In [9]: s.eval(x!=4,1)
Out[9]: (False,)

In [10]: s.constraints
Out[10]: [<Bool x_0_32 == 0x4>]

Running python3.6.9 on ubuntu 18.04.

Name: claripy
Version: 8.20.1.7
Summary: An abstraction layer for constraint solvers
Home-page: https://github.com/angr/claripy
Author: None
Author-email: None
License: UNKNOWN
Location: /home/<redacted>/.local/lib/python3.6/site-packages
Requires: decorator, z3-solver, pysmt, future, cachetools
Required-by: angr

is_true and is_false are only meant to catch extremely simple cases. In general, our simplifications only handle purely local simplifications, i.e. not requiring context from constraints.

I believe your example will be handled if you use the replacement solver and add x == 4 as a replacement, though.

I don't pretend to know claripy internals well enough to fully understand why this doesn't work, but it seems to be intended behaviour, so I'll close the issue

Thanks for getting back so quickly!