-
Notifications
You must be signed in to change notification settings - Fork 44
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
Type safety violation and soundness bug with parameterized domain #759
Comments
Thanks for filing this issue! However, I don't think I agree that this qualifies as a type safety violation or a soundness issue; IMO it's simply the case that 2vyper's struct encoding has some potentially unexpected properties. Viper monomorphizes generic domains. I.e., from Viper's point of view, the program you and 2vyper wrote is essentially equivalent to:
So, conceptually, the encoding defines different get and set functions for every type. The effect of setting the value of a struct member of a given type constrains the value of the getter for the same type, but says nothing about the getters of other types. So in the example, the Int value of member 0 of the struct is set to 10, but its Bool (and Ref, and Seq, etc) values are unconstrained, so it makes sense that you can prove that its Bool value is either true or false. I agree that this is probably unexpected when using 2vyper's struct encoding as a general struct encoding, and that it is not so obvious that domains with type parameters conceptually declare functions with type parameters s.t. two versions of the same function with different type arguments are essentially independent. But knowing that, I think Viper's behavior makes sense. |
Thanks for the explanation! The resulting behavior is certainly a bit strange, but the explanation makes sense. (This might be a nice example to add to the Viper tutorial to demonstrate the way Viper handles parameterized domains.) |
The following domain definition is from the 2vyper project here. $Struct defines a domain giving a unique identifier to every element of a struct, and $StructOps defines a domain for struct operations, parameterized by the type of struct element you are getting or setting. (Struct is defined in this way to avoid axioms that need to quantify over types.)
The following does not raise a type error, allowing us to set a Bool variable to an Int value. Furthermore, it exposes a soundness bug, since the assertion (y == true) || (y == false) passes, despite the actual value of y being 10.
It seems that the SMT solver assumes that the type checker is catching all type errors, and so relies on the original type of y as a Bool to vacuously verify
assert (y == true) || (y == false)
. However, the type checker does not catch the type safety violation of setting y to 10, leading the solver to verify the false statement(y == true) || (y == false)
.(Credit to my advisor Thomas Wies on realizing that the type safety violation can lead to a soundness bug!)
The text was updated successfully, but these errors were encountered: