-
Notifications
You must be signed in to change notification settings - Fork 1
Panic freedom #3
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
base: master
Are you sure you want to change the base?
Conversation
franziskuskiefer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
I think there are two different categories in here on overflow/underflow issues. This is definitely the typical class of issues in code like this. And I guess we didn't always review well.
- When the function is returning an error anyway, these should really be caught and errors returned.
- For non-failing functions it's a little tricky. Because we don't always want a
Result. At the same time would it be nice to do better here. One easy option would be_checkedvariants that return aResult. Another option would be returning a tuple with aboolon whether the result is correct or not. Then the caller can decide what to do with it. This would be breaking though.
In some cases overflows may also not be possible and we may want to treat code differently, depending on whether that can happen or not.
tls_codec/src/tls_vec.rs
Outdated
| /// The serialized len | ||
| #[inline(always)] | ||
| fn tls_serialized_byte_length(&$self) -> usize { | ||
| hax_lib::fstar!("admit ()"); // overflow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah these kind of functions are difficult. We really don't want to return a Result but it's of course true that this may overflow.
In most cases this can't happen. But on a TlsVecU32 (or the slice version) on a 32 bit system this may indeed happen.
We could add a variant of the function with a _checked postfix and return a Result there.
| // large and write it out. | ||
| let (tls_serialized_len, byte_length) = $self.get_content_lengths()?; | ||
|
|
||
| hax_lib::fstar!("admit ()"); // Need to prove unwrap for usize to U24 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe U24 should be implemented separately here to allow more checks?
tls_codec/src/tls_vec.rs
Outdated
|
|
||
| #[inline] | ||
| fn index(&self, i: usize) -> &T { | ||
| hax_lib::fstar!("admit ()"); // index precondition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the length. Maybe we should have a checked version here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here it is really the caller's responsibility to provide a valid index so it makes sense to have a precondition. I switched to this in the latest version.
tls_codec/src/lib.rs
Outdated
| fn from(value: U24) -> usize { | ||
| const LEN: usize = core::mem::size_of::<usize>(); | ||
| let mut usize_bytes = [0u8; LEN]; | ||
| hax_lib::assume!(LEN == 8); // https://github.com/cryspen/hax/issues/1702 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may also be 4 on 32 bit systems. Maybe we should just assume >= 4? We don't want to support smaller than 32 bit systems here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I wanted to do LEN == 4 || LEN == 8. Unfortunately this doesn't work because of a hax bug (the issue that is linked in the comment).
Thanks for the feedback. I'll have a look at the suggestions and push a new version with some more disruptive changes to fix some over/underflows. |
I just pushed a new version where additions and subtractions are replaced by |
|
@franziskuskiefer I made a try for having a checked version for |
franziskuskiefer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The _checked versions lgtm.
I'm a little concerned about performance of the unchecked versions because they produce significantly more code now.
| type Error = Error; | ||
|
|
||
| fn try_from(value: usize) -> Result<Self, Self::Error> { | ||
| fn try_from(value: usize) -> Result<Self, Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't hax handle this? It would be better to not having to keep these two types in sync manually.
| } | ||
| #[inline] | ||
| fn tls_serialized_len(&self) -> usize { | ||
| 1usize |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Swapping the match and computation avoids computation in case of None.
| #[inline] | ||
| fn tls_serialized_len(&self) -> usize { | ||
| 1usize | ||
| .checked_add(match self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you check the performance? All the additional checks may make things slower. Since the result will be wrong in either case, we should make sure not to slow down things here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@franziskuskiefer I ran the benchmarks, and for TLS Serailize (vector and slice), there is a performance regression. I takes about +38% of runtime. So what do you think we should do?
|
@maximebuyse @karthikbhargavan what are the next steps here? |
We could schedule some time next week to finish this. The main question here is about the checked version of |
26c59bc to
476a951
Compare
This is a first step for proving panic freedom. Extraction using hax and F* type checking works, but some parts are admitted (with comments). The most common reasons for admits are:
usizetoU24is unsafe (should work because it is used only on valid values but that makes it hard to prove)debug_asserts are not proven for nowsize_ofis inlined by hax in types but not values hax#1702eqtypehax#1700&mutparameters hax#1584core::cmp::PartialEq::eqby F* equality which is sometimes not available hax#1704The current state works with hax branch
tls-codec-panic-freedom