Skip to content

Commit

Permalink
Check MSRV and prefer Option for propagation (#2766)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Jan 2, 2024
1 parent 8a25767 commit d214aac
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 44 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/windows-bindgen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: windows-bindgen

on:
pull_request:
push:
paths-ignore:
- '.github/ISSUE_TEMPLATE/**'
branches:
- master

env:
RUSTFLAGS: -Dwarnings

jobs:
cargo_sys:
name: Check
strategy:
matrix:
rust: [1.70.0, stable, nightly]
runs-on:
- windows-latest
- ubuntu-latest
runs-on: ${{ matrix.runs-on }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Prepare
run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
- name: Check
run: cargo check -p windows-bindgen --all-features
30 changes: 30 additions & 0 deletions .github/workflows/windows-metadata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: windows-metadata

on:
pull_request:
push:
paths-ignore:
- '.github/ISSUE_TEMPLATE/**'
branches:
- master

env:
RUSTFLAGS: -Dwarnings

jobs:
cargo_sys:
name: Check
strategy:
matrix:
rust: [1.70.0, stable, nightly]
runs-on:
- windows-latest
- ubuntu-latest
runs-on: ${{ matrix.runs-on }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Prepare
run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
- name: Check
run: cargo check -p windows-metadata --all-features
30 changes: 30 additions & 0 deletions .github/workflows/windows-version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: windows-version

on:
pull_request:
push:
paths-ignore:
- '.github/ISSUE_TEMPLATE/**'
branches:
- master

env:
RUSTFLAGS: -Dwarnings

jobs:
cargo_sys:
name: Check
strategy:
matrix:
rust: [1.56.0, stable, nightly]
runs-on:
- windows-latest
- ubuntu-latest
runs-on: ${{ matrix.runs-on }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Prepare
run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
- name: Check
run: cargo check -p windows-version --all-features
2 changes: 1 addition & 1 deletion crates/libs/bindgen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "windows-bindgen"
version = "0.52.0"
authors = ["Microsoft"]
edition = "2021"
rust-version = "1.56"
rust-version = "1.70"
license = "MIT OR Apache-2.0"
description = "Windows metadata compiler"
repository = "https://github.com/microsoft/windows-rs"
Expand Down
5 changes: 1 addition & 4 deletions crates/libs/bindgen/src/rust/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,7 @@ pub fn writer(writer: &Writer, def: metadata::Field) -> TokenStream {
}

fn initializer(writer: &Writer, def: metadata::Field) -> Option<TokenStream> {
let Some(value) = constant(def) else {
return None;
};

let value = constant(def)?;
let mut input = value.as_str();

let metadata::Type::TypeDef(def, _) = def.ty(None) else {
Expand Down
6 changes: 1 addition & 5 deletions crates/libs/core/src/strings/hstring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,7 @@ impl HSTRING {
}

fn get_header(&self) -> Option<&Header> {
if let Some(header) = &self.0 {
unsafe { Some(header.as_ref()) }
} else {
None
}
self.0.map(|header| unsafe { header.as_ref() })
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/libs/metadata/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "windows-metadata"
version = "0.52.0"
authors = ["Microsoft"]
edition = "2021"
rust-version = "1.64"
rust-version = "1.70"
license = "MIT OR Apache-2.0"
description = "Windows metadata reader"
repository = "https://github.com/microsoft/windows-rs"
Expand Down
61 changes: 28 additions & 33 deletions crates/libs/metadata/src/file.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use super::*;
type Result<T> = std::result::Result<T, ()>;

pub struct File {
pub reader: *const Reader,
Expand Down Expand Up @@ -45,16 +44,12 @@ unsafe impl Sync for File {}

impl File {
pub fn new(bytes: Vec<u8>) -> Option<Self> {
Self::ok(bytes).ok()
}

fn ok(bytes: Vec<u8>) -> Result<Self> {
let mut result = File { bytes, reader: std::ptr::null(), strings: 0, blobs: 0, tables: Default::default() };

let dos = result.bytes.view_as::<IMAGE_DOS_HEADER>(0)?;

if dos.e_magic != IMAGE_DOS_SIGNATURE || result.bytes.copy_as::<u32>(dos.e_lfanew as usize)? != IMAGE_NT_SIGNATURE {
return Err(());
return None;
}

let file_offset = dos.e_lfanew as usize + std::mem::size_of::<u32>();
Expand All @@ -71,20 +66,20 @@ impl File {
let optional = result.bytes.view_as::<IMAGE_OPTIONAL_HEADER64>(optional_offset)?;
(optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize].VirtualAddress, result.bytes.view_as_slice_of::<IMAGE_SECTION_HEADER>(optional_offset + std::mem::size_of::<IMAGE_OPTIONAL_HEADER64>(), file.NumberOfSections as usize)?)
}
_ => return Err(()),
_ => return None,
};

let clr = result.bytes.view_as::<IMAGE_COR20_HEADER>(offset_from_rva(section_from_rva(sections, com_virtual_address)?, com_virtual_address))?;

if clr.cb != std::mem::size_of::<IMAGE_COR20_HEADER>() as u32 {
return Err(());
return None;
}

let metadata_offset = offset_from_rva(section_from_rva(sections, clr.MetaData.VirtualAddress)?, clr.MetaData.VirtualAddress);
let metadata = result.bytes.view_as::<METADATA_HEADER>(metadata_offset)?;

if metadata.signature != METADATA_SIGNATURE {
return Err(());
return None;
}

// The METADATA_HEADER struct is not a fixed size so have to offset a little more carefully.
Expand Down Expand Up @@ -306,7 +301,7 @@ impl File {
result.tables[NestedClass::TABLE].set_data(&mut view);
result.tables[GenericParam::TABLE].set_data(&mut view);

Ok(result)
Some(result)
}

pub fn usize(&self, row: usize, table: usize, column: usize) -> usize {
Expand Down Expand Up @@ -356,64 +351,64 @@ impl File {
}
}

fn section_from_rva(sections: &[IMAGE_SECTION_HEADER], rva: u32) -> Result<&IMAGE_SECTION_HEADER> {
sections.iter().find(|&s| rva >= s.VirtualAddress && rva < s.VirtualAddress + unsafe { s.Misc.VirtualSize }).ok_or(())
fn section_from_rva(sections: &[IMAGE_SECTION_HEADER], rva: u32) -> Option<&IMAGE_SECTION_HEADER> {
sections.iter().find(|&s| rva >= s.VirtualAddress && rva < s.VirtualAddress + unsafe { s.Misc.VirtualSize })
}

fn offset_from_rva(section: &IMAGE_SECTION_HEADER, rva: u32) -> usize {
(rva - section.VirtualAddress + section.PointerToRawData) as usize
}

trait View {
fn view_as<T>(&self, offset: usize) -> Result<&T>;
fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> Result<&[T]>;
fn copy_as<T: Copy>(&self, offset: usize) -> Result<T>;
fn view_as_str(&self, offset: usize) -> Result<&[u8]>;
fn is_proper_length<T>(&self, offset: usize) -> Result<()>;
fn is_proper_length_and_alignment<T>(&self, offset: usize, count: usize) -> Result<*const T>;
fn view_as<T>(&self, offset: usize) -> Option<&T>;
fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> Option<&[T]>;
fn copy_as<T: Copy>(&self, offset: usize) -> Option<T>;
fn view_as_str(&self, offset: usize) -> Option<&[u8]>;
fn is_proper_length<T>(&self, offset: usize) -> Option<()>;
fn is_proper_length_and_alignment<T>(&self, offset: usize, count: usize) -> Option<*const T>;
}

impl View for [u8] {
fn view_as<T>(&self, offset: usize) -> Result<&T> {
unsafe { Ok(&*self.is_proper_length_and_alignment(offset, 1)?) }
fn view_as<T>(&self, offset: usize) -> Option<&T> {
unsafe { Some(&*self.is_proper_length_and_alignment(offset, 1)?) }
}

fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> Result<&[T]> {
unsafe { Ok(std::slice::from_raw_parts(self.is_proper_length_and_alignment(offset, len)?, len)) }
fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> Option<&[T]> {
unsafe { Some(std::slice::from_raw_parts(self.is_proper_length_and_alignment(offset, len)?, len)) }
}

fn copy_as<T>(&self, offset: usize) -> Result<T> {
fn copy_as<T>(&self, offset: usize) -> Option<T> {
self.is_proper_length::<T>(offset)?;

unsafe {
let mut data = std::mem::MaybeUninit::zeroed().assume_init();
std::ptr::copy_nonoverlapping(self[offset..].as_ptr(), &mut data as *mut T as *mut u8, std::mem::size_of::<T>());
Ok(data)
Some(data)
}
}

fn view_as_str(&self, offset: usize) -> Result<&[u8]> {
fn view_as_str(&self, offset: usize) -> Option<&[u8]> {
let buffer = &self[offset..];
let index = buffer.iter().position(|c| *c == b'\0').ok_or(())?;
Ok(&self[offset..offset + index])
let index = buffer.iter().position(|c| *c == b'\0')?;
Some(&self[offset..offset + index])
}

fn is_proper_length<T>(&self, offset: usize) -> Result<()> {
fn is_proper_length<T>(&self, offset: usize) -> Option<()> {
if offset + std::mem::size_of::<T>() <= self.len() {
Ok(())
Some(())
} else {
Err(())
None
}
}

fn is_proper_length_and_alignment<T>(&self, offset: usize, count: usize) -> Result<*const T> {
fn is_proper_length_and_alignment<T>(&self, offset: usize, count: usize) -> Option<*const T> {
self.is_proper_length::<T>(offset * count)?;
let ptr = &self[offset] as *const u8 as *const T;

if ptr.align_offset(std::mem::align_of::<T>()) == 0 {
Ok(ptr)
Some(ptr)
} else {
Err(())
None
}
}
}

0 comments on commit d214aac

Please sign in to comment.