Skip to content

Commit

Permalink
ref: Replace unsafe strlen usage by safe Rust
Browse files Browse the repository at this point in the history
Removes the `unsafe` usage of C strlen and unchecked utf8 decoding
from `File::str`, replacing it with safe (but panicing) Rust code.
This also documents the method at the same time.
  • Loading branch information
Swatinem committed Jul 21, 2022
1 parent 42f05aa commit 72fc91d
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 8 deletions.
3 changes: 3 additions & 0 deletions crates/libs/metadata/Cargo.toml
Expand Up @@ -10,3 +10,6 @@ repository = "https://github.com/microsoft/windows-rs"
[package.metadata.docs.rs]
default-target = "x86_64-pc-windows-msvc"
targets = []

[dependencies]
memchr = "2.5.0"
4 changes: 0 additions & 4 deletions crates/libs/metadata/src/imp.rs
Expand Up @@ -13,10 +13,6 @@ pub struct METADATA_HEADER {

pub const METADATA_SIGNATURE: u32 = 0x424A_5342;

extern "C" {
pub fn strlen(cs: *const u8) -> usize;
}

/// A coded index (see codes.rs) is a table index that may refer to different tables. The size of the column in memory
/// must therefore be large enough to hold an index for a row in the largest possible table. This function determines
/// this size for the given winmd file.
Expand Down
16 changes: 12 additions & 4 deletions crates/libs/metadata/src/reader/file.rs
Expand Up @@ -333,13 +333,21 @@ impl File {
}
}

/// Returns the string from the `#Strings` stream as referenced by
/// the (table, row, column) triple.
///
/// # Panics
///
/// * When any element of the (table, row, column) triple is invalid.
/// * When the offset in the string table is out of bounds.
/// * When no null terminator can be found in the string table.
/// * When the null-terminated string is not valid utf-8.
pub fn str(&self, row: usize, table: usize, column: usize) -> &str {
let offset = self.strings + self.usize(row, table, column);

unsafe {
let len = strlen(self.bytes.as_ptr().add(offset));
std::str::from_utf8_unchecked(&self.bytes[offset..offset + len])
}
let bytes = &self.bytes[offset..];
let nul_pos = memchr::memchr(0, bytes).unwrap();
std::str::from_utf8(&bytes[..nul_pos]).unwrap()
}

pub fn blob(&self, row: usize, table: usize, column: usize) -> &[u8] {
Expand Down

0 comments on commit 72fc91d

Please sign in to comment.