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

Challenge 13: Safety of CStr #150

Open
celinval opened this issue Nov 4, 2024 · 2 comments
Open

Challenge 13: Safety of CStr #150

celinval opened this issue Nov 4, 2024 · 2 comments
Labels
Challenge Used to tag a challenge

Comments

@celinval
Copy link

celinval commented Nov 4, 2024

Challenge link: https://model-checking.github.io/verify-rust-std/challenges/0013-cstr.html

@celinval celinval added the Challenge Used to tag a challenge label Nov 4, 2024
@Yenyun035
Copy link

Yenyun035 commented Nov 22, 2024

Edit: After discussion, we were recommended to implement the Invariant manually using ub_checks::Invariant, as similar to this code.


@celinval We (Team 2) decided to work on this challenge for a week while waiting for Kani issue #3711 to unblock #59 Part 3.

For Part 1, we are writing a safety invariant for CStr. From the doc and Kani PR#3270 we found that #[derive(Invariant)] macro and #[safety_constraint(...)] attribute look useful. We are thinking about writing the safety invariant in c_str.rs like:

#[cfg(kani)]
use crate::kani;

// Struct-level CStr safety invariant
#[derive(kani::Arbitrary)] // Might be useful when verifying methods that take a CStr as input
#[derive(kani::Invariant)]
#[safety_constraint(inner.len() > 0 && inner[inner.len() - 1] == 0 && !inner[..inner.len() - 1].contains(&0))]
pub struct CStr {
    // comments omitted
    inner: [c_char],
}

// Test harness
// pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError>
#[kani::proof]
#[kani::unwind(16)]  // Proof bounded by array length
fn check_from_bytes_until_nul() {
    const ARR_LEN: usize = 16;
    let mut string: [u8; ARR_LEN] = kani::any();
    // ensure that there is at least one null byte
    let idx: usize = kani::any_where(|x| *x >= 0 && *x < ARR_LEN);
    string[idx] = 0;

    let c_str = CStr::from_bytes_until_nul(&string).unwrap();
    assert!(c_str.is_safe());
}

However, the compilation of core (using the kani script) failed due to the following error:

error[E0404]: expected trait, found derive macro `core::kani::Invariant`
   --> /Users/yew005/Docs/Academic/CMU/Fall24/practicum/vrs/library/core/src/ffi/c_str.rs:109:10
    |
109 | #[derive(kani::Invariant)]
    |          ^^^^^^^^^^^^^^^ not a trait

We thought that this should be supported in Kani 0.54.0, but we were not able to compile. How could we fix it?

@rajathkotyal, @lanfeima, @MWDZ for visibility.

@rajathkotyal
Copy link

Upon some research, The compilation error could be due to the fact we are trying to include an external dep (kani::Invariant) into the source code compilation process, So even with the use of cfg["kani"] flag, the compiler tries to parse and resolve all macros and attributes. It cannot find kani::Invariant within the core crate.

There seems to be some ambiguity in the code / with my understanding. Some insight on this would help.

zhassan-aws pushed a commit that referenced this issue Nov 26, 2024
Towards #150 

### Changes
* Added a `CStr` Safety Invariant
* Added a harness for `from_bytes_until_nul`, the harness covers:
    * The input slice contains a single null byte at the end;
    * The input slice contains no null bytes;
    * The input slice contains intermediate null bytes

### Discussion
* [Safety invariant
implementation](#150 (comment))
* [Input array
generation](#181)

### Verification Result
`./scripts/run-kani.sh --kani-args --harness ffi::c_str::verify`

```
// array size 16
Checking harness ffi::c_str::verify::check_from_bytes_until_nul...

VERIFICATION RESULT:
 ** 0 of 140 failed (5 unreachable)

VERIFICATION:- SUCCESSFUL
Verification Time: 7.3023376s

Complete - 1 successfully verified harnesses, 0 failures, 1 total.
```

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 and MIT licenses.
tautschnig pushed a commit that referenced this issue Nov 28, 2024
Towards #150 

Changes
Added harnesses for count_bytes

Verification Result
```
Checking harness ffi::c_str::verify::check_count_bytes...

VERIFICATION RESULT:
 ** 0 of 241 failed (5 unreachable)

VERIFICATION:- SUCCESSFUL
Verification Time: 5.377671s
```
celinval pushed a commit that referenced this issue Nov 29, 2024
Towards #150 

### Changes
* Added harnesses for `to_bytes` and `to_bytes_with_nul`
* Added a small fix to `count_bytes`

Verification Result:
```
Checking harness ffi::c_str::verify::check_to_bytes_with_nul...

VERIFICATION RESULT:
 ** 0 of 179 failed (5 unreachable)

VERIFICATION:- SUCCESSFUL
Verification Time: 88.397385s

Checking harness ffi::c_str::verify::check_to_bytes...

VERIFICATION RESULT:
 ** 0 of 180 failed (5 unreachable)

VERIFICATION:- SUCCESSFUL
Verification Time: 79.66312s

Checking harness ffi::c_str::verify::check_from_bytes_until_nul...

VERIFICATION RESULT:
 ** 0 of 132 failed (5 unreachable)

VERIFICATION:- SUCCESSFUL
Verification Time: 28.593569s

Complete - 3 successfully verified harnesses, 0 failures, 3 total.
```
tautschnig pushed a commit that referenced this issue Dec 1, 2024
Towards #150 

### Changes
* Added a harness for `is_empty`
* Added a small optimization for `arbitray_cstr`

### Verification Result
```
SUMMARY:
 ** 0 of 193 failed (5 unreachable)

VERIFICATION:- SUCCESSFUL
Verification Time: 51.462265s

Complete - 1 successfully verified harnesses, 0 failures, 1 total.
```
tautschnig pushed a commit that referenced this issue Dec 3, 2024
Towards #150 

Verifies that the CStr safety invariant holds after calling :

from_bytes_with_nul --> core::ffi::c_str module
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Challenge Used to tag a challenge
Projects
None yet
Development

No branches or pull requests

3 participants