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

Configures Miri to use tree borrows, fixes remaining errors #821

Merged
merged 1 commit into from
Aug 23, 2024

Conversation

zslayton
Copy link
Contributor

@zslayton zslayton commented Aug 22, 2024

Related to #794.

Miri's tree borrows aliasing model is more permissive than stacked borrows (the default), which is known to reject some programs that are actually safe.

This PR configures our CI miri check to use tree borrows and addresses several of Miri's complaints. This is enough to satisfy the tests currently in CI (the tests for the experimental serde feature).

There are still some issues to investigate. When running Miri on the entire test suite, it complains about at least one more problem, though it's unclear whether it's actually a potential problem or another limitation in its aliasing model. This patch is an improvement, however, and I'd rather not block these changes as we look into the others.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Copy link
Contributor Author

@zslayton zslayton left a comment

Choose a reason for hiding this comment

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

🗺️ PR Tour 🧭

on: [push, pull_request]
on: [ push, pull_request ]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🗺️ Some autoformatting happened in this file.

Comment on lines +73 to +79
if let Some(ptr) = encoding_buffer_ptr {
let encoding_buffer = unsafe { ptr_to_ref::<'_, BumpVec<'_, u8>>(*ptr).as_slice() };
// Write our top level encoding buffer's contents to the output sink.
output.write_all(encoding_buffer)?;
// Flush the output sink, which may have its own buffers.
output.flush()?;
}
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 ported this more succinct version from the 1.1 writer; notice that it more narrowly scopes the encoding_buffer reference.

Comment on lines +22 to +29
/// Helper function that turns a raw pointer into an immutable reference of the specified type.
///
/// The caller is responsible for confirming that `ptr` is a valid reference to some value
/// of type `T`.
pub(crate) unsafe fn ptr_to_ref<'a, T>(ptr: *mut ()) -> &'a T {
let typed_ptr: *const T = ptr.cast();
&*typed_ptr
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🗺️ Previously we only had a ptr_to_mut_ref which meant we were getting a mutable reference even where a read-only reference would suffice.

Some(ptr) => unsafe { ptr_to_mut_ref::<'_, BumpVec<'_, u8>>(*ptr).as_slice() },
Some(ptr) => unsafe { ptr_to_ref::<'_, BumpVec<'_, u8>>(*ptr).as_slice() },
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🗺️ In flush() we only need to read from the encoding buffer, so we don't need a mut ref.

Comment on lines -471 to +476
let symbol_table: &mut SymbolTable =
&mut unsafe { &mut *self.encoding_context.get() }.symbol_table;
let macro_table: &mut MacroTable =
&mut unsafe { &mut *self.encoding_context.get() }.macro_table;
let encoding_context_ref = unsafe { &mut *self.encoding_context.get() };
let EncodingContext {
macro_table,
symbol_table,
..
} = encoding_context_ref;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🗺️ Here we get a single mutable reference and then use safe code to destructure it into two mutable references.

Comment on lines -533 to +536
let allocator: &BumpAllocator = self.context().allocator();
let context_ref = EncodingContextRef::new(allocator.alloc_with(|| self.context()));
let context_ref = self.context();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🗺️ This was copying the EncodingContextRef to the bump allocator so it would survive the lifetime 'top...but it was already going to survive that because the EncodingContext lives in the ExpandingReader.

@zslayton zslayton marked this pull request as ready for review August 23, 2024 13:38
@zslayton zslayton merged commit 7c170cc into main Aug 23, 2024
32 checks passed
@zslayton zslayton deleted the miri-bugfixes branch August 23, 2024 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants