-
Notifications
You must be signed in to change notification settings - Fork 104
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
Valid value checks does not check char
surrogate values
#3241
Comments
I've been investigating this issue and here's what I've found out. First, the Note: 1114111 is 0x10FFFF (i.e., I tried to special-case the diff --git a/kani-compiler/src/kani_middle/transform/check_values.rs b/kani-compiler/src/kani_middle/transform/check_values.rs
index a7d0f14d270..253963a4ef6 100644
--- a/kani-compiler/src/kani_middle/transform/check_values.rs
+++ b/kani-compiler/src/kani_middle/transform/check_values.rs
@@ -839,8 +839,21 @@ pub fn ty_validity_per_offset(
ty: Ty,
current_offset: usize,
) -> Result<Vec<ValidValueReq>, String> {
+ debug!(typ=?ty, kind=?ty.kind(), "ty_validity_per_offset");
let layout = ty.layout().unwrap().shape();
let ty_req = || {
+ if ty.kind() == TyKind::RigidTy(RigidTy::Char) {
+ let shape = ty.layout().unwrap().shape();
+ let value_size = match shape.abi {
+ ValueAbi::Scalar(Scalar::Initialized { value, .. })
+ | ValueAbi::ScalarPair(Scalar::Initialized { value, .. }, _) => {
+ Some(value.size(machine_info))
+ }
+ _ => None,
+ };
+ return vec![ValidValueReq { offset: 0, size: value_size.unwrap(), valid_range: WrappingRange { start: 0, end: 0xD7FF }},
+ ValidValueReq { offset: 0, size: value_size.unwrap(), valid_range: WrappingRange { start: 0xE000, end: 0x10FFFF }}]
+ };
if let Some(mut req) = ValidValueReq::try_from_ty(machine_info, ty) However, that didn't have the intended effect as each range check is being encoded separately. In other words, this change will generate two separate checks as follows:
which doesn't work well because it's requiring It's not clear to me that the check generation should be done this way for multiple ranges. For example, in this code SourceOp::BytesValidity { ranges, target_ty, rvalue } => {
let value = body.new_assignment(rvalue, &mut source, InsertPosition::Before);
let rvalue_ptr = Rvalue::AddressOf(Mutability::Not, Place::from(value));
for range in ranges {
let result = build_limits(body, &range, rvalue_ptr.clone(), &mut source);
let msg =
format!("Undefined Behavior: Invalid value of type `{target_ty}`",);
body.add_check(
tcx,
&self.check_type,
&mut source,
InsertPosition::Before,
result,
&msg,
);
}
} in which cases does it make sense to generate more than one check? Another option is to extend |
Unfortunately, the option of extending
It's not clear to me such changes would pay off if Would it be OK to change the range loop above so that |
Ensure value validity checks for `char` in Kani matches the Rust documentation: > A char value must not be a surrogate (i.e., must not be in the range 0xD800..=0xDFFF) and must be equal to or less than char::MAX. The existing code was relying on the compiler ABI information, which can only express one continuous value range for value validity. But `char` is a special case, and the Rust compiler understands the gap in valid `char`. This change makes Kani compiler aware of this gap too. Resolves #3241 By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
I tried this code:
using the following command line invocation:
with Kani version: 0.52.0
I expected to see this happen: A valid value check failure
Instead, this happened: An unreachable block being reached due to UB
The text was updated successfully, but these errors were encountered: