-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Add a footer in FileEncoder and check for it in MemDecoder #124686
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,10 +40,9 @@ use rustc_span::hygiene::HygieneDecodeContext; | |
mod cstore_impl; | ||
|
||
/// A reference to the raw binary version of crate metadata. | ||
/// A `MetadataBlob` internally is just a reference counted pointer to | ||
/// the actual data, so cloning it is cheap. | ||
#[derive(Clone)] | ||
pub(crate) struct MetadataBlob(pub(crate) OwnedSlice); | ||
/// This struct applies [`MemDecoder`]'s validation when constructed | ||
/// so that later constructions are guaranteed to succeed. | ||
pub(crate) struct MetadataBlob(OwnedSlice); | ||
|
||
impl std::ops::Deref for MetadataBlob { | ||
type Target = [u8]; | ||
|
@@ -54,6 +53,19 @@ impl std::ops::Deref for MetadataBlob { | |
} | ||
} | ||
|
||
impl MetadataBlob { | ||
/// Runs the [`MemDecoder`] validation and if it passes, constructs a new [`MetadataBlob`]. | ||
pub fn new(slice: OwnedSlice) -> Result<Self, ()> { | ||
if MemDecoder::new(&slice, 0).is_ok() { Ok(Self(slice)) } else { Err(()) } | ||
} | ||
|
||
/// Since this has passed the validation of [`MetadataBlob::new`], this returns bytes which are | ||
/// known to pass the [`MemDecoder`] validation. | ||
pub fn bytes(&self) -> &OwnedSlice { | ||
&self.0 | ||
} | ||
} | ||
|
||
/// A map from external crate numbers (as decoded from some crate file) to | ||
/// local crate numbers (as generated during this session). Each external | ||
/// crate may refer to types in other external crates, and each has their | ||
|
@@ -165,7 +177,14 @@ pub(super) trait Metadata<'a, 'tcx>: Copy { | |
fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { | ||
let tcx = self.tcx(); | ||
DecodeContext { | ||
opaque: MemDecoder::new(self.blob(), pos), | ||
// FIXME: This unwrap should never panic because we check that it won't when creating | ||
// `MetadataBlob`. Ideally we'd just have a `MetadataDecoder` and hand out subslices of | ||
// it as we do elsewhere in the compiler using `MetadataDecoder::split_at`. But we own | ||
// the data for the decoder so holding onto the `MemDecoder` too would make us a | ||
// self-referential struct which is downright goofy because `MetadataBlob` is already | ||
// self-referential. Probably `MemDecoder` should contain an `OwnedSlice`, but that | ||
// demands a significant refactoring due to our crate graph. | ||
opaque: MemDecoder::new(self.blob(), pos).unwrap(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This won't solve the root problem but we could have a (safe) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could, but the perf run indicates that the overhead from this is so low we can't measure it so the duplicated check seems fine to me since this PR is in response to a complete lack of checks. |
||
cdata: self.cdata(), | ||
blob: self.blob(), | ||
sess: self.sess().or(tcx.map(|tcx| tcx.sess)), | ||
|
@@ -393,7 +412,7 @@ impl<'a, 'tcx> TyDecoder for DecodeContext<'a, 'tcx> { | |
where | ||
F: FnOnce(&mut Self) -> R, | ||
{ | ||
let new_opaque = MemDecoder::new(self.opaque.data(), pos); | ||
let new_opaque = self.opaque.split_at(pos); | ||
let old_opaque = mem::replace(&mut self.opaque, new_opaque); | ||
let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode); | ||
let r = f(self); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -182,15 +182,13 @@ impl SerializedDepGraph { | |
pub fn decode<D: Deps>(d: &mut MemDecoder<'_>) -> Arc<SerializedDepGraph> { | ||
// The last 16 bytes are the node count and edge count. | ||
debug!("position: {:?}", d.position()); | ||
let (node_count, edge_count, graph_size) = | ||
d.with_position(d.len() - 3 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| { | ||
let (node_count, edge_count) = | ||
d.with_position(d.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| { | ||
debug!("position: {:?}", d.position()); | ||
let node_count = IntEncodedWithFixedSize::decode(d).0 as usize; | ||
let edge_count = IntEncodedWithFixedSize::decode(d).0 as usize; | ||
let graph_size = IntEncodedWithFixedSize::decode(d).0 as usize; | ||
(node_count, edge_count, graph_size) | ||
(node_count, edge_count) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the motivation for dropping the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The graph_size check was intended to detect this sort of issue. I wasn't sure what errors we'd get out of it, and experience has shown that nearly all reported ICEs are due to truncated files. So detecting truncation more deliberately which is what this PR does, seems more sensible. |
||
}); | ||
assert_eq!(d.len(), graph_size); | ||
debug!("position: {:?}", d.position()); | ||
|
||
debug!(?node_count, ?edge_count); | ||
|
@@ -606,8 +604,6 @@ impl<D: Deps> EncoderState<D> { | |
debug!("position: {:?}", encoder.position()); | ||
IntEncodedWithFixedSize(node_count).encode(&mut encoder); | ||
IntEncodedWithFixedSize(edge_count).encode(&mut encoder); | ||
let graph_size = encoder.position() + IntEncodedWithFixedSize::ENCODED_SIZE; | ||
IntEncodedWithFixedSize(graph_size as u64).encode(&mut encoder); | ||
debug!("position: {:?}", encoder.position()); | ||
// Drop the encoder so that nothing is written after the counts. | ||
let result = encoder.finish(); | ||
|
Uh oh!
There was an error while loading. Please reload this page.