Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

Support for symbolic strings #88

Merged
merged 3 commits into from Mar 11, 2021
Merged

Conversation

alastairreid
Copy link
Contributor

@alastairreid alastairreid commented Feb 9, 2021

Composed of

  • Efficient support for creating symbolic Vec.
  • Tests involving strings
  • Creating a new top-level directory 'runtime' to contain C support code required to interface between what the Rust library expects from the C library and the set of operations provided by different verifiers.
    • This will probably end up being a combination of code that is needed by all verifiers and code that is only needed with a subset of the verifier backends that we support. So it will end up requiring conditional compilation.
    • For now all it contains is support for allocating aligned memory blocks (used by crates like Regex).
    • In the near future, I will add code to support code that uses pthreads but only requires one thread. (i.e., to support almost every thread-safe library)
  • Tests involving the standard Regex crate

@google-cla google-cla bot added the cla: yes Contributor has signed CLA label Feb 9, 2021
@alastairreid
Copy link
Contributor Author

Note that this change should not be pushed for review until the script_fixes_2 change is merged.

verification-annotations/src/klee.rs Outdated Show resolved Hide resolved
runtime/Makefile Outdated Show resolved Hide resolved
runtime/Makefile Outdated Show resolved Hide resolved
verifier::assume(i.is_ascii_alphabetic());
}

for i in a.as_bytes().iter() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need the .iter() here? for does that for you. You can also do all this in one assertion:

verifier::assert!(a.as_bytes().iter().all(char::is_ascii))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm dropping the .iter() here and in the other place that I used '.as_bytes().iter()' a few lines above.

But I find that this point-free style less readable so I prefer the for loop.

}
match String::from_utf8(r) {
Ok(r) => r,
Err(_) => reject(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this doesn't matter very much, but shouldn't this reject() be unreachable()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reject() is equivalent to assume(false) and so it prevents the verifier from reporting errors involving this path. (In KLEE, it silently halts the current path exploration.)

unreachable() generates an error that is treated as a verification error.

In this case, the function is meant to be generating a legal string so we would not want to report an error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But you already assume all the bytes are ascii, is the Err branch still reachable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see.

I am 99.9999% certain that this cannot fail.
But suppose I am wrong, then I would not want to report 'unreachable' because it would be an error in the verification support code not in the code being verified.

It would be good though to get some sort of report that there is a problem in the verification harness.
We should think about this a bit.

I think that this relates to a general problem in verification where you accidentally over-constrain the inputs so that you are not testing inputs that actually matter. In the extreme case (that is surprisingly common), the constraints are contradictory so there are no inputs and the verification is vacuously true.
I have been thinking that we should tackle that using a variation of what hardware engineers do when doing random testing: the System Verilog language lets you gather statistics about how many of the random inputs are in certain ranges - if a given range doesn't have enough values in it, you either need to test more or modify your test.
This would make sense as a proptest extension while for propverify we would just check that each range of interest is satisfiable.
(But exploring this is a problem for the future)

#[cfg_attr(feature = "verifier-crux", crux_test)]
fn bytes() {
let a = verifier::verifier_nondet_bytes(8);
for i in a.iter() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for i in &a { will call a.iter(). Note the &, otherwise it calls a.into_iter() which moves a and you can no longer use it.

}

// force string to be a legal int
for i in a.as_bytes().into_iter() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need .into_iter().

}

// force string to be a legal int
for i in a.as_bytes().into_iter() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need .into_iter().

@alastairreid
Copy link
Contributor Author

Sorry this is taking a while to get back to - I wanted to get KLEE up and running with the new cargo-verify frontend before revisiting this.
It will probably be a few days before I get back to this.

Alastair Reid added 3 commits March 10, 2021 14:52
This is primarily a test that stubbing out feature tests
and implementing posix_memalign fixes the problems
we were seeing when trying to use the Regex library.

As expected, the Regex library is a major verification
bottleneck and you can only use very small, simple regexes.
So regexes are still not viable to use at the moment.
@alastairreid
Copy link
Contributor Author

I acted on all comments apart from the one about using unreachable instead of reject.
(Neither is perfect (see discussion above) - but I think that reject is closer.)

Also, I moved the regex tests into demos/bottlenecks/regex since they were more about testing our ability to cope with language/tool features than they were about testing the verification annotations crate.

(Since I have fixed everything, I would normally self-approve. But that seems to be disabled.)

@alastairreid alastairreid merged commit a209a86 into project-oak:main Mar 11, 2021
@alastairreid
Copy link
Contributor Author

(It wasn't disabled after all - confusing UI)

@alastairreid alastairreid deleted the strings branch March 11, 2021 11:32
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla: yes Contributor has signed CLA
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants