Skip to content

Commit

Permalink
Abstract reading of files to Read + Seek traits
Browse files Browse the repository at this point in the history
  • Loading branch information
russellbanks committed Feb 20, 2024
1 parent 9807179 commit b70d38b
Show file tree
Hide file tree
Showing 15 changed files with 89 additions and 113 deletions.
24 changes: 1 addition & 23 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ strip = true
base16ct = { version = "0.2.0", features = ["std"] }
base64ct = { version = "1.6.0", features = ["std"] }
bitflags = "2.4.2"
byteorder = "1.5.0"
chrono = { version = "0.4.34", features = ["serde"] }
clap = { version = "4.5.1", features = ["derive", "cargo", "env"] }
color-eyre = { version = "0.6.2", default-features = false }
Expand All @@ -38,6 +37,7 @@ itertools = "0.12.1"
keyring = "2.3.2"
memmap2 = "0.9.4"
msi = "0.7.0"
num-traits = "0.2.18"
num_cpus = "1.16.0"
nutype = { version = "0.4.0", features = ["serde"] }
object = "0.32.2"
Expand All @@ -60,7 +60,6 @@ tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros", "fs"] }
url = { version = "2.5.0", features = ["serde"] }
uuid = { version = "1.7.0", features = ["v4"] }
versions = "6.1.0"
zerocopy = "0.7.32"
zip = { version = "0.6.6", default-features = false, features = ["deflate"] }

[target.'cfg(any(windows, target_os = "macos"))'.dependencies]
Expand Down
11 changes: 9 additions & 2 deletions src/download_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use color_eyre::eyre::{eyre, Result, WrapErr};
use futures_util::{stream, StreamExt, TryStreamExt};
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
use itertools::Itertools;
use memmap2::Mmap;
use reqwest::header::{HeaderValue, CONTENT_DISPOSITION, LAST_MODIFIED};
use reqwest::Client;
use sha2::{Digest, Sha256};
Expand All @@ -14,6 +15,7 @@ use std::cmp::min;
use std::collections::HashMap;
use std::fs::File;
use std::future::Future;
use std::io::Cursor;
use std::path::Path;
use tokio::io::AsyncWriteExt;
use uuid::Uuid;
Expand Down Expand Up @@ -137,8 +139,13 @@ pub async fn process_files<'a>(
file_name,
last_modified,
}| async move {
let mut file_analyser =
FileAnalyser::new(&file, Cow::Owned(file_name), false, zip_relative_file_path)?;
let map = unsafe { Mmap::map(&file) }?;
let mut file_analyser = FileAnalyser::new(
Cursor::new(map.as_ref()),
Cow::Owned(file_name),
false,
zip_relative_file_path,
)?;
file_analyser.architecture =
find_architecture(url.as_str()).or(file_analyser.architecture);
file_analyser.installer_sha_256 = sha_256;
Expand Down
20 changes: 8 additions & 12 deletions src/exe/utils.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
use byteorder::{LittleEndian, ReadBytesExt};
use color_eyre::eyre::Result;
use std::io::Cursor;
use num_traits::{PrimInt, Unsigned};
use object::ReadRef;
use std::mem;

pub const fn align(value: usize, boundary: usize) -> usize {
if value % boundary == 0 {
pub fn align<T: PrimInt + Unsigned>(value: T, boundary: T) -> T {
if value % boundary == T::zero() {
value
} else {
value + (boundary - (value % boundary))
}
}

pub fn get_widestring_size(data: &[u8], offset: usize) -> Result<usize> {
let mut cursor = Cursor::new(data);
pub fn get_widestring_size<'data, R: ReadRef<'data>>(data: R, offset: u64) -> u64 {
let mut index = offset;
for i in (index..data.len()).step_by(mem::size_of::<u16>()) {
cursor.set_position(i as u64);

if cursor.read_u16::<LittleEndian>()? == 0 {
for i in (index..data.len().unwrap()).step_by(mem::size_of::<u16>()) {
if data.read_at::<u16>(i).unwrap() == &0 {
index = i;
break;
}
}

Ok(index - offset)
(index - offset) / mem::size_of::<u16>() as u64
}
21 changes: 9 additions & 12 deletions src/exe/vs_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::exe::utils::get_widestring_size;
use color_eyre::eyre::Result;
use object::ReadRef;
use std::mem;
use zerocopy::FromBytes;

/// Represents a header for a `VS_VERSION` structure.
///
Expand All @@ -16,23 +15,21 @@ pub struct VSHeader<'data> {
}

impl<'data> VSHeader<'data> {
pub fn parse(data: &'data [u8], base_offset: usize) -> Result<(usize, Self)> {
pub fn parse<R: ReadRef<'data>>(data: R, base_offset: u64) -> Result<(u64, Self)> {
let mut offset = base_offset;

let length = data.read_at(offset as u64).unwrap();
offset += mem::size_of::<u16>();
let length = data.read(&mut offset).unwrap();

let value_length = data.read_at(offset as u64).unwrap();
offset += mem::size_of::<u16>();
let value_length = data.read(&mut offset).unwrap();

let type_value = data.read_at(offset as u64).unwrap();
offset += mem::size_of::<u16>();
let type_value = data.read(&mut offset).unwrap();

let widestring_size = get_widestring_size(data, offset)?;
let widestring_size = get_widestring_size(data, offset);

let key = FromBytes::slice_from(&data[offset..offset + widestring_size]).unwrap();
let key_size = (key.len() + 1) * mem::size_of::<u16>();
offset += key_size;
let key = data
.read_slice(&mut offset, usize::try_from(widestring_size)?)
.unwrap();
offset += mem::size_of::<u16>() as u64;

Ok((
offset,
Expand Down
10 changes: 6 additions & 4 deletions src/exe/vs_string.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::exe::utils::{align, get_widestring_size};
use crate::exe::vs_header::VSHeader;
use color_eyre::eyre::Result;
use zerocopy::FromBytes;
use object::ReadRef;

/// Represents a [`String`](https://docs.microsoft.com/en-us/windows/win32/menurc/string-str) structure.
pub struct VSString<'data> {
Expand All @@ -10,12 +10,14 @@ pub struct VSString<'data> {
}
impl<'data> VSString<'data> {
/// Parse a `VSString` object at the given virtual address.
pub fn parse(data: &'data [u8], base_offset: usize) -> Result<Self> {
pub fn parse<R: ReadRef<'data>>(data: R, base_offset: u64) -> Result<Self> {
let (mut offset, header) = VSHeader::parse(data, base_offset)?;
offset = align(offset, 4);

let widestring_size = get_widestring_size(data, offset)?;
let value = FromBytes::slice_from(&data[offset..offset + widestring_size]).unwrap();
let widestring_size = get_widestring_size(data, offset);
let value = data
.read_slice_at(offset, usize::try_from(widestring_size)?)
.unwrap();

Ok(Self { header, value })
}
Expand Down
11 changes: 6 additions & 5 deletions src/exe/vs_string_file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::exe::utils::align;
use crate::exe::vs_header::VSHeader;
use crate::exe::vs_string_table::VSStringTable;
use color_eyre::eyre::Result;
use object::ReadRef;

/// Represents a [`StringFileInfo`](https://docs.microsoft.com/en-us/windows/win32/menurc/stringfileinfo) structure.
pub struct VSStringFileInfo<'data> {
Expand All @@ -10,17 +11,17 @@ pub struct VSStringFileInfo<'data> {
}
impl<'data> VSStringFileInfo<'data> {
/// Parse a `VSStringFileInfo` structure at the given [`RVA`](RVA).
pub fn parse(pe: &'data [u8], base_offset: usize) -> Result<Self> {
let (mut offset, header) = VSHeader::parse(pe, base_offset)?;
pub fn parse<R: ReadRef<'data>>(data: R, base_offset: u64) -> Result<Self> {
let (mut offset, header) = VSHeader::parse(data, base_offset)?;
let mut consumed = offset - base_offset;
offset = align(offset, 4);

let mut children = Vec::<VSStringTable>::new();

while consumed < (*header.length as usize) {
let child = VSStringTable::parse(pe, offset)?;
while consumed < u64::from(*header.length) {
let child = VSStringTable::parse(data, offset)?;

offset += *child.header.length as usize;
offset += u64::from(*child.header.length);
offset = align(offset, 4);
consumed = offset - base_offset;
children.push(child);
Expand Down
7 changes: 4 additions & 3 deletions src/exe/vs_string_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::exe::utils::align;
use crate::exe::vs_header::VSHeader;
use crate::exe::vs_string::VSString;
use color_eyre::eyre::Result;
use object::ReadRef;
use std::collections::HashMap;

/// Represents a [`StringTable`](https://docs.microsoft.com/en-us/windows/win32/menurc/stringtable) structure.
Expand All @@ -11,17 +12,17 @@ pub struct VSStringTable<'data> {
}
impl<'data> VSStringTable<'data> {
/// Parse a `VSStringTable` structure at the given RVA.
pub fn parse(data: &'data [u8], base_offset: usize) -> Result<Self> {
pub fn parse<R: ReadRef<'data>>(data: R, base_offset: u64) -> Result<Self> {
let (mut offset, header) = VSHeader::parse(data, base_offset)?;
let mut consumed = offset - base_offset;
offset = align(offset, 4);

let mut children = Vec::<VSString>::new();

while consumed < *header.length as usize {
while consumed < u64::from(*header.length) {
let child = VSString::parse(data, offset)?;

offset += *child.header.length as usize;
offset += u64::from(*child.header.length);
offset = align(offset, 4);
consumed = offset - base_offset;
children.push(child);
Expand Down
8 changes: 3 additions & 5 deletions src/exe/vs_var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::exe::var_dword::VarDword;
use crate::exe::vs_header::VSHeader;
use color_eyre::eyre::Result;
use object::ReadRef;
use std::mem;

/// Represents a [`Var`](https://docs.microsoft.com/en-us/windows/win32/menurc/var-str) structure.
pub struct VSVar<'data> {
Expand All @@ -12,17 +11,16 @@ pub struct VSVar<'data> {
}
impl<'data> VSVar<'data> {
/// Parse a `VSVar` structure at the given [`RVA`](RVA).
pub fn parse(data: &'data [u8], base_offset: usize) -> Result<Self> {
pub fn parse<R: ReadRef<'data>>(data: R, base_offset: u64) -> Result<Self> {
let (mut offset, header) = VSHeader::parse(data, base_offset)?;
let mut consumed = offset;
offset = align(offset, 4);

let mut children = Vec::<&'data VarDword>::new();

while consumed < (*header.length as usize) {
let child = data.read_at(offset as u64).unwrap();
while consumed < u64::from(*header.length) {
let child = data.read(&mut offset).unwrap();

offset += mem::size_of::<VarDword>();
offset = align(offset, 4);
consumed = offset - base_offset;
children.push(child);
Expand Down
11 changes: 6 additions & 5 deletions src/exe/vs_var_file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::exe::utils::align;
use crate::exe::vs_header::VSHeader;
use crate::exe::vs_var::VSVar;
use color_eyre::eyre::Result;
use object::ReadRef;

/// Represents a [`VarFileInfo`](https://docs.microsoft.com/en-us/windows/win32/menurc/varfileinfo) structure.
pub struct VSVarFileInfo<'data> {
Expand All @@ -10,17 +11,17 @@ pub struct VSVarFileInfo<'data> {
}
impl<'data> VSVarFileInfo<'data> {
/// Parse a `VSVarFileInfo` structure at the given [`RVA`](RVA).
pub fn parse(pe: &'data [u8], base_offset: usize) -> Result<Self> {
let (mut offset, header) = VSHeader::parse(pe, base_offset)?;
pub fn parse<R: ReadRef<'data>>(data: R, base_offset: u64) -> Result<Self> {
let (mut offset, header) = VSHeader::parse(data, base_offset)?;
let mut consumed = offset;
offset = align(offset, 4);

let mut children = Vec::<VSVar>::new();

while consumed < (*header.length as usize) {
let child = VSVar::parse(pe, offset)?;
while consumed < u64::from(*header.length) {
let child = VSVar::parse(data, offset)?;

offset += *child.header.length as usize;
offset += u64::from(*child.header.length);
offset = align(offset, 4);
consumed = offset - base_offset;
children.push(child);
Expand Down
Loading

0 comments on commit b70d38b

Please sign in to comment.