Guest User

Untitled

a guest
Apr 24th, 2025
261
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.74 KB | None | 0 0
  1. pub const BLOB_MAGIC: [u8; 4] = [b'P', b'V', b'M', b'\0'];
  2. pub type BlobLen = u64;
  3. pub const BLOB_LEN_SIZE: usize = core::mem::size_of::<BlobLen>();
  4. pub const BLOB_LEN_OFFSET: usize = BLOB_MAGIC.len() + 1;
  5.  
  6. pub const SECTION_MEMORY_CONFIG: u8 = 1;
  7. pub const SECTION_RO_DATA: u8 = 2;
  8. pub const SECTION_RW_DATA: u8 = 3;
  9. pub const SECTION_IMPORTS: u8 = 4;
  10. pub const SECTION_EXPORTS: u8 = 5;
  11. pub const SECTION_CODE_AND_JUMP_TABLE: u8 = 6;
  12. pub const SECTION_OPT_DEBUG_STRINGS: u8 = 128;
  13. pub const SECTION_OPT_DEBUG_LINE_PROGRAMS: u8 = 129;
  14. pub const SECTION_OPT_DEBUG_LINE_PROGRAM_RANGES: u8 = 130;
  15. pub const SECTION_END_OF_FILE: u8 = 0;
  16.  
  17. pub const BLOB_VERSION_V1_64: u8 = 0;
  18. pub const BLOB_VERSION_V1_32: u8 = 1;
  19.  
  20. pub const VERSION_DEBUG_LINE_PROGRAM_V1: u8 = 1;
  21.  
  22. impl<'a> Reader<'a, ArcBytes> {
  23.     fn read_slice_as_bytes(&mut self, length: usize) -> Result<ArcBytes, ProgramParseError> {
  24.         let range = self.read_slice_as_range(length)?;
  25.         Ok(self.blob.subslice(range))
  26.     }
  27.  
  28.     fn read_section_as_bytes(&mut self, out_section: &mut u8, expected_section: u8) -> Result<ArcBytes, ProgramParseError> {
  29.         if *out_section != expected_section {
  30.             return Ok(ArcBytes::default());
  31.         }
  32.  
  33.         let section_length = self.read_varint()? as usize;
  34.         let range = self.read_slice_as_range(section_length)?;
  35.         *out_section = self.read_byte()?;
  36.  
  37.         Ok(self.blob.subslice(range))
  38.     }
  39. }
  40.  
  41.  
  42. impl ProgramParts {
  43.     pub fn from_bytes(blob: ArcBytes) -> Result<Self, ProgramParseError> {
  44.         if !blob.starts_with(&BLOB_MAGIC) {
  45.             return Err(ProgramParseError(ProgramParseErrorKind::Other(
  46.                 "blob doesn't start with the expected magic bytes",
  47.             )));
  48.         }
  49.  
  50.         let mut reader = Reader {
  51.             blob: &blob,
  52.             position: BLOB_MAGIC.len(),
  53.         };
  54.  
  55.         let blob_version = reader.read_byte()?;
  56.         let is_64_bit = if blob_version == BLOB_VERSION_V1_32 {
  57.             false
  58.         } else if blob_version == BLOB_VERSION_V1_64 {
  59.             true
  60.         } else {
  61.             return Err(ProgramParseError(ProgramParseErrorKind::UnsupportedVersion {
  62.                 version: blob_version,
  63.             }));
  64.         };
  65.  
  66.         let blob_len = BlobLen::from_le_bytes(reader.read_slice(BLOB_LEN_SIZE)?.try_into().unwrap());
  67.         if blob_len != blob.len() as u64 {
  68.             return Err(ProgramParseError(ProgramParseErrorKind::Other(
  69.                 "blob size doesn't match the blob length metadata",
  70.             )));
  71.         }
  72.  
  73.         let mut parts = ProgramParts {
  74.             is_64_bit,
  75.             ..ProgramParts::default()
  76.         };
  77.  
  78.         let mut section = reader.read_byte()?;
  79.         if section == SECTION_MEMORY_CONFIG {
  80.             let section_length = reader.read_varint()?;
  81.             let position = reader.position;
  82.             parts.ro_data_size = reader.read_varint()?;
  83.             parts.rw_data_size = reader.read_varint()?;
  84.             parts.stack_size = reader.read_varint()?;
  85.             if position + section_length as usize != reader.position {
  86.                 return Err(ProgramParseError(ProgramParseErrorKind::Other(
  87.                     "the memory config section contains more data than expected",
  88.                 )));
  89.             }
  90.             section = reader.read_byte()?;
  91.         }
  92.  
  93.         parts.ro_data = reader.read_section_as_bytes(&mut section, SECTION_RO_DATA)?;
  94.         parts.rw_data = reader.read_section_as_bytes(&mut section, SECTION_RW_DATA)?;
  95.  
  96.         if section == SECTION_IMPORTS {
  97.             let section_length = reader.read_varint()? as usize;
  98.             let section_start = reader.position;
  99.             let import_count = reader.read_varint()?;
  100.             if import_count > VM_MAXIMUM_IMPORT_COUNT {
  101.                 return Err(ProgramParseError(ProgramParseErrorKind::Other("too many imports")));
  102.             }
  103.  
  104.             let Some(import_offsets_size) = import_count.checked_mul(4) else {
  105.                 return Err(ProgramParseError(ProgramParseErrorKind::Other("the imports section is invalid")));
  106.             };
  107.  
  108.             parts.import_offsets = reader.read_slice_as_bytes(import_offsets_size as usize)?;
  109.             let Some(import_symbols_size) = section_length.checked_sub(reader.position - section_start) else {
  110.                 return Err(ProgramParseError(ProgramParseErrorKind::Other("the imports section is invalid")));
  111.             };
  112.  
  113.             parts.import_symbols = reader.read_slice_as_bytes(import_symbols_size)?;
  114.             section = reader.read_byte()?;
  115.         }
  116.  
  117.         parts.exports = reader.read_section_as_bytes(&mut section, SECTION_EXPORTS)?;
  118.         parts.code_and_jump_table = reader.read_section_as_bytes(&mut section, SECTION_CODE_AND_JUMP_TABLE)?;
  119.         parts.debug_strings = reader.read_section_as_bytes(&mut section, SECTION_OPT_DEBUG_STRINGS)?;
  120.         parts.debug_line_programs = reader.read_section_as_bytes(&mut section, SECTION_OPT_DEBUG_LINE_PROGRAMS)?;
  121.         parts.debug_line_program_ranges = reader.read_section_as_bytes(&mut section, SECTION_OPT_DEBUG_LINE_PROGRAM_RANGES)?;
  122.  
  123.         while (section & 0b10000000) != 0 {
  124.             // We don't know this section, but it's optional, so just skip it.
  125.             #[cfg(feature = "logging")]
  126.             log::debug!("Skipping unsupported optional section: {}", section);
  127.             let section_length = reader.read_varint()?;
  128.             reader.skip(section_length as usize)?;
  129.             section = reader.read_byte()?;
  130.         }
  131.  
  132.         if section != SECTION_END_OF_FILE {
  133.             return Err(ProgramParseError(ProgramParseErrorKind::UnexpectedSection {
  134.                 offset: reader.position - 1,
  135.                 section,
  136.             }));
  137.         }
  138.  
  139.         Ok(parts)
  140.     }
  141. }
  142.  
Advertisement
Add Comment
Please, Sign In to add comment