about summary refs log tree commit diff
diff options
context:
space:
mode:
authorniluxv <niluxv.opensource.C-h2ty6xl@yandex.com>2023-08-05 20:20:41 +0200
committerniluxv <niluxv.opensource.C-h2ty6xl@yandex.com>2023-10-10 09:59:39 +0200
commite7a3c341dd517465a326ef693d49f6238789f96b (patch)
treec41c3c7f1426ead40869f6afe03f59ad26f32be3
parentfa6d1e75125d9c94c21a58c2301492026031fcb8 (diff)
downloadrust-e7a3c341dd517465a326ef693d49f6238789f96b.tar.gz
rust-e7a3c341dd517465a326ef693d49f6238789f96b.zip
Use pointers instead of `usize` addresses for landing pads
This bring unwind and personality code more in line with strict-provenance
-rw-r--r--library/panic_unwind/src/gcc.rs2
-rw-r--r--library/std/src/sys/personality/dwarf/eh.rs66
-rw-r--r--library/std/src/sys/personality/gcc.rs9
-rw-r--r--library/unwind/src/lib.rs1
-rw-r--r--library/unwind/src/libunwind.rs14
5 files changed, 50 insertions, 42 deletions
diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs
index 08858dd92be..54eb6627c01 100644
--- a/library/panic_unwind/src/gcc.rs
+++ b/library/panic_unwind/src/gcc.rs
@@ -63,7 +63,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
         _uwe: uw::_Unwind_Exception {
             exception_class: rust_exception_class(),
             exception_cleanup,
-            private: [0; uw::unwinder_private_data_size],
+            private: [core::ptr::null(); uw::unwinder_private_data_size],
         },
         canary: &CANARY,
         cause: data,
diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs
index 79624703a4c..dd0a76100e2 100644
--- a/library/std/src/sys/personality/dwarf/eh.rs
+++ b/library/std/src/sys/personality/dwarf/eh.rs
@@ -1,6 +1,7 @@
 //! Parsing of GCC-style Language-Specific Data Area (LSDA)
 //! For details see:
 //!  * <https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html>
+//!  * <https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html>
 //!  * <https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf>
 //!  * <https://www.airs.com/blog/archives/460>
 //!  * <https://www.airs.com/blog/archives/464>
@@ -37,17 +38,19 @@ pub const DW_EH_PE_indirect: u8 = 0x80;
 
 #[derive(Copy, Clone)]
 pub struct EHContext<'a> {
-    pub ip: usize,                             // Current instruction pointer
-    pub func_start: usize,                     // Address of the current function
-    pub get_text_start: &'a dyn Fn() -> usize, // Get address of the code section
-    pub get_data_start: &'a dyn Fn() -> usize, // Get address of the data section
+    pub ip: *const u8,                             // Current instruction pointer
+    pub func_start: *const u8,                     // Pointer to the current function
+    pub get_text_start: &'a dyn Fn() -> *const u8, // Get pointer to the code section
+    pub get_data_start: &'a dyn Fn() -> *const u8, // Get pointer to the data section
 }
 
+/// Landing pad.
+type LPad = *const u8;
 pub enum EHAction {
     None,
-    Cleanup(usize),
-    Catch(usize),
-    Filter(usize),
+    Cleanup(LPad),
+    Catch(LPad),
+    Filter(LPad),
     Terminate,
 }
 
@@ -82,21 +85,21 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
 
     if !USING_SJLJ_EXCEPTIONS {
         while reader.ptr < action_table {
-            let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
-            let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
-            let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
+            let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr();
+            let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr();
+            let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr();
             let cs_action_entry = reader.read_uleb128();
             // Callsite table is sorted by cs_start, so if we've passed the ip, we
             // may stop searching.
-            if ip < func_start + cs_start {
+            if ip < func_start.wrapping_add(cs_start) {
                 break;
             }
-            if ip < func_start + cs_start + cs_len {
+            if ip < func_start.wrapping_add(cs_start + cs_len) {
                 if cs_lpad == 0 {
                     return Ok(EHAction::None);
                 } else {
-                    let lpad = lpad_base + cs_lpad;
-                    return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad));
+                    let lpad = lpad_base.wrapping_add(cs_lpad);
+                    return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
                 }
             }
         }
@@ -106,12 +109,12 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
         // SjLj version:
         // The "IP" is an index into the call-site table, with two exceptions:
         // -1 means 'no-action', and 0 means 'terminate'.
-        match ip as isize {
+        match ip.addr() as isize {
             -1 => return Ok(EHAction::None),
             0 => return Ok(EHAction::Terminate),
             _ => (),
         }
-        let mut idx = ip;
+        let mut idx = ip.addr();
         loop {
             let cs_lpad = reader.read_uleb128();
             let cs_action_entry = reader.read_uleb128();
@@ -119,17 +122,18 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
             if idx == 0 {
                 // Can never have null landing pad for sjlj -- that would have
                 // been indicated by a -1 call site index.
-                let lpad = (cs_lpad + 1) as usize;
-                return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad));
+                // FIXME(strict provenance)
+                let lpad = ptr::from_exposed_addr((cs_lpad + 1) as usize);
+                return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
             }
         }
     }
 }
 
 unsafe fn interpret_cs_action(
-    action_table: *mut u8,
+    action_table: *const u8,
     cs_action_entry: u64,
-    lpad: usize,
+    lpad: LPad,
 ) -> EHAction {
     if cs_action_entry == 0 {
         // If cs_action_entry is 0 then this is a cleanup (Drop::drop). We run these
@@ -138,7 +142,7 @@ unsafe fn interpret_cs_action(
     } else {
         // If lpad != 0 and cs_action_entry != 0, we have to check ttype_index.
         // If ttype_index == 0 under the condition, we take cleanup action.
-        let action_record = (action_table as *mut u8).offset(cs_action_entry as isize - 1);
+        let action_record = action_table.offset(cs_action_entry as isize - 1);
         let mut action_reader = DwarfReader::new(action_record);
         let ttype_index = action_reader.read_sleb128();
         if ttype_index == 0 {
@@ -161,15 +165,16 @@ unsafe fn read_encoded_pointer(
     reader: &mut DwarfReader,
     context: &EHContext<'_>,
     encoding: u8,
-) -> Result<usize, ()> {
+) -> Result<*const u8, ()> {
     if encoding == DW_EH_PE_omit {
         return Err(());
     }
 
     // DW_EH_PE_aligned implies it's an absolute pointer value
     if encoding == DW_EH_PE_aligned {
-        reader.ptr = reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<usize>())?);
-        return Ok(reader.read::<usize>());
+        reader.ptr =
+            reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<*const u8>())?);
+        return Ok(reader.read::<*const u8>());
     }
 
     let mut result = match encoding & 0x0F {
@@ -190,18 +195,21 @@ unsafe fn read_encoded_pointer(
         // relative to address of the encoded value, despite the name
         DW_EH_PE_pcrel => reader.ptr.expose_addr(),
         DW_EH_PE_funcrel => {
-            if context.func_start == 0 {
+            if context.func_start.is_null() {
                 return Err(());
             }
-            context.func_start
+            context.func_start.expose_addr()
         }
-        DW_EH_PE_textrel => (*context.get_text_start)(),
-        DW_EH_PE_datarel => (*context.get_data_start)(),
+        DW_EH_PE_textrel => (*context.get_text_start)().expose_addr(),
+        DW_EH_PE_datarel => (*context.get_data_start)().expose_addr(),
         _ => return Err(()),
     };
 
+    // FIXME(strict provenance)
+    let mut result: *const u8 = ptr::from_exposed_addr::<u8>(result);
+
     if encoding & DW_EH_PE_indirect != 0 {
-        result = *ptr::from_exposed_addr::<usize>(result);
+        result = *(result.cast::<*const u8>());
     }
 
     Ok(result)
diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs
index 559d2c7db47..6f317131145 100644
--- a/library/std/src/sys/personality/gcc.rs
+++ b/library/std/src/sys/personality/gcc.rs
@@ -38,7 +38,6 @@
 
 use super::dwarf::eh::{self, EHAction, EHContext};
 use crate::ffi::c_int;
-use libc::uintptr_t;
 use unwind as uw;
 
 // Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
@@ -160,9 +159,9 @@ cfg_if::cfg_if! {
                         uw::_Unwind_SetGR(
                             context,
                             UNWIND_DATA_REG.0,
-                            exception_object as uintptr_t,
+                            exception_object as uw::_Unwind_Ptr,
                         );
-                        uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
+                        uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null());
                         uw::_Unwind_SetIP(context, lpad);
                         return uw::_URC_INSTALL_CONTEXT;
                     }
@@ -222,9 +221,9 @@ cfg_if::cfg_if! {
                         uw::_Unwind_SetGR(
                             context,
                             UNWIND_DATA_REG.0,
-                            exception_object as uintptr_t,
+                            exception_object.cast(),
                         );
-                        uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
+                        uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null());
                         uw::_Unwind_SetIP(context, lpad);
                         uw::_URC_INSTALL_CONTEXT
                     }
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 94a91dd357c..e86408a9ed2 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -4,6 +4,7 @@
 #![feature(staged_api)]
 #![feature(c_unwind)]
 #![feature(cfg_target_abi)]
+#![feature(strict_provenance)]
 #![cfg_attr(not(target_env = "msvc"), feature(libc))]
 #![allow(internal_features)]
 
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index a2bfa8e96dd..dba64aa74ce 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -1,6 +1,6 @@
 #![allow(nonstandard_style)]
 
-use libc::{c_int, c_void, uintptr_t};
+use libc::{c_int, c_void};
 
 #[repr(C)]
 #[derive(Debug, Copy, Clone, PartialEq)]
@@ -19,8 +19,8 @@ pub enum _Unwind_Reason_Code {
 pub use _Unwind_Reason_Code::*;
 
 pub type _Unwind_Exception_Class = u64;
-pub type _Unwind_Word = uintptr_t;
-pub type _Unwind_Ptr = uintptr_t;
+pub type _Unwind_Word = *const u8;
+pub type _Unwind_Ptr = *const u8;
 pub type _Unwind_Trace_Fn =
     extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code;
 
@@ -214,7 +214,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe
     // On Android or ARM/Linux, these are implemented as macros:
 
     pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
-        let mut val: _Unwind_Word = 0;
+        let mut val: _Unwind_Word = core::ptr::null();
         _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
                         &mut val as *mut _ as *mut c_void);
         val
@@ -229,14 +229,14 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe
     pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
                                 -> _Unwind_Word {
         let val = _Unwind_GetGR(ctx, UNWIND_IP_REG);
-        (val & !1) as _Unwind_Word
+        val.map_addr(|v| v & !1)
     }
 
     pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
                                 value: _Unwind_Word) {
         // Propagate thumb bit to instruction pointer
-        let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1;
-        let value = value | thumb_state;
+        let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG).addr() & 1;
+        let value = value.map_addr(|v| v | thumb_state);
         _Unwind_SetGR(ctx, UNWIND_IP_REG, value);
     }