Skip to content

simd_div and simd_rem don't check for overflow cases #1970

Closed
@adpaco-aws

Description

Both simd_div and simd_rem are missing an overflow check that is done for the regular division operators (i.e., / and %). Consider this example:

#![feature(repr_simd, platform_intrinsics)]

#[repr(simd)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct i32x2(i32, i32);

extern "platform-intrinsic" {
    fn simd_div<T>(x: T, y: T) -> T;
    fn simd_rem<T>(x: T, y: T) -> T;
}

#[kani::proof]
fn test_normal() {
    let val_1: i32 = kani::any();
    let val_2: i32 = kani::any();
    kani::assume(val_1 == i32::MIN);
    kani::assume(val_2 == -1);
    let result: i32 = val_1 / val_2;
}

#[kani::proof]
fn test_simd() {
    let val_1 = kani::any();
    kani::assume(val_1 == i32::MIN);
    let values_1 = i32x2(val_1, val_1);
    let val_2 = kani::any();
    kani::assume(val_2 == -1);
    let values_2 = i32x2(val_2, val_2);
    let result = unsafe { simd_div(values_1, values_2) };
}

This is verification output for test_normal:

RESULTS:
Check 1: test_normal.assertion.1
         - Status: SUCCESS
         - Description: "attempt to divide by zero"
         - Location: tests/kani/Intrinsics/SIMD/Operators/div_rem.rs:19:23 in function test_normal

Check 2: test_normal.assertion.2
         - Status: FAILURE
         - Description: "attempt to divide with overflow"
         - Location: tests/kani/Intrinsics/SIMD/Operators/div_rem.rs:19:23 in function test_normal

Check 3: test_normal.division-by-zero.1
         - Status: SUCCESS
         - Description: "division by zero"
         - Location: tests/kani/Intrinsics/SIMD/Operators/div_rem.rs:19:23 in function test_normal

This is the verification output for test_simd:

Check 1: division-by-zero.1
         - Status: SUCCESS
         - Description: "division by zero"

Check 2: division-by-zero.2
         - Status: SUCCESS
         - Description: "division by zero"

There are several concerns here:

  • The overflow check is missing when using the vector operator.
  • The "attempt to divide by zero" check is missing when using the vector operator.

Note that Kani tweaks the output a little bit in this example. In particular, for properties with class division-by-zero it omits the variables, the original outputs are:

Check 3: test_normal.division-by-zero.1
         - Status: SUCCESS
         - Description: "division by zero in var_10 / var_11"
         - Location: tests/kani/Intrinsics/SIMD/Operators/div_rem.rs:19:23 in function test_normal
Check 1: division-by-zero.1
         - Status: SUCCESS
         - Description: "division by zero in var_16[0] / var_17[0]"

Check 2: division-by-zero.2
         - Status: SUCCESS
         - Description: "division by zero in var_16[1] / var_17[1]"

In diffblue/cbmc#7367 I asked the CBMC folks about this missing check, but it turns out these checks are being generated by MIR! I don't think that the "attempt to divide by zero" property is needed here (as it's basically a duplicate of "division by zero"), but it's unclear how to insert the "attempt to divide with overflow" property for SIMD intrinsics.

Metadata

Assignees

Labels

[E] Unsupported UBUndefined behavior that Kani does not detect

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions