From 975ffd17fa3129efcd0e74bb925e48cd1d6bdabc Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Thu, 21 Jul 2022 09:52:58 +0200 Subject: [PATCH] ref: Replace unsafe strlen usage by safe Rust 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. --- crates/libs/metadata/src/imp.rs | 4 ---- crates/libs/metadata/src/reader/file.rs | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/libs/metadata/src/imp.rs b/crates/libs/metadata/src/imp.rs index 4c380fd4d8..27a735a451 100644 --- a/crates/libs/metadata/src/imp.rs +++ b/crates/libs/metadata/src/imp.rs @@ -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. diff --git a/crates/libs/metadata/src/reader/file.rs b/crates/libs/metadata/src/reader/file.rs index e195cf12a2..cbbb949127 100644 --- a/crates/libs/metadata/src/reader/file.rs +++ b/crates/libs/metadata/src/reader/file.rs @@ -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 = bytes.iter().position(|&c| c == 0).expect("expected null-terminated C-string"); + std::str::from_utf8(&bytes[..nul_pos]).expect("expected valid utf-8 C-string") } pub fn blob(&self, row: usize, table: usize, column: usize) -> &[u8] {