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

ModelCacheMixin does not handle extra_constraints correctly for min #324

Open
g-kouv opened this issue Nov 30, 2022 · 3 comments
Open

ModelCacheMixin does not handle extra_constraints correctly for min #324

g-kouv opened this issue Nov 30, 2022 · 3 comments
Assignees
Labels

Comments

@g-kouv
Copy link

g-kouv commented Nov 30, 2022

Description

Calling min with non-empty extra constraints results in an incorrect value, because the expression is found in _min_exhausted and cached results are incorrectly used to calculate the minimum.

A simple reproducer:

import claripy

s = claripy.Solver()
x = claripy.BVS("x", 64)
y = claripy.BVS("y", 64)
s.add(x - y >= 4)
s.add(y > 0)
print(s.min(x))
print(s.min(x, extra_constraints=[x > 1]))

The last line prints 3 even though the correct answer is 2.

A simple solution would skip checking _min_exhausted and using cached results when extra constraints are passed. A related bug seems to has been fixed previously in 9d4b861.

The issue also seems to apply to max and possibly eval.

Steps to reproduce the bug

No response

Environment

No response

Additional context

No response

@g-kouv g-kouv added the bug label Nov 30, 2022
@ltfish ltfish self-assigned this Jan 2, 2023
@SanWieb
Copy link

SanWieb commented Mar 9, 2023

I found a bug which I think it casued by the same issue: ModelCacheMixin takes a invalid solution from the cache.

Reproducer:

import claripy

ast = claripy.BVS("a", 64) + 0xff

s = claripy.Solver()

print("Min 1: ", s.min(ast))
print("Max 1: ", s.max(ast))

print("Min 2: ", s.min(ast))
print("Max 2: ", s.max(ast))

s = claripy.Solver()

print("")
print("Max 1: ", s.max(ast))
print("Min 1: ", s.min(ast))

print("Max 2: ", s.max(ast))
print("Min 2: ", s.min(ast))

Produced output:

Min 1:  0
Max 1:  18446744073709551615
Min 2:  255
Max 2:  18446744073709551615

Max 1:  18446744073709551615
Min 1:  0
Max 2:  257
Min 2:  0

@zwimer
Copy link
Member

zwimer commented Sep 2, 2024

@g-kouv When I run this directly with z3: It looks like something wonky is happening in Z3 here, printing out the input and output of result = solver.check(extra_constraints) in backend_z3.py gives:

solver.check([UGE(x_0_64 - x_1_64, 4), UGT(x_1_64, 0), And(UGE(x_0_64, 0), ULE(x_0_64, 3))]) = sat

Which should be false mathematically unless I'm missing something obvious:

https://www.wolframalpha.com/input?i=x-y%3E%3D4+and+y%3E0+and+x%3E%3D0+and+x%3C%3D3
^ My sanity check

@zwimer
Copy link
Member

zwimer commented Sep 2, 2024

Actually, I think that's the case. Adding the constraint x>y fixes the above, so the weird behavior I mentioned is likely due to emulating underflow/overflow.

twizmwazin added a commit that referenced this issue Sep 3, 2024
twizmwazin added a commit that referenced this issue Sep 3, 2024
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

4 participants