borrowscope_runtime/tracker/
unsafe_code.rs

1//! Unsafe code tracking: raw pointers, unsafe blocks, FFI, transmute
2
3use super::TRACKER;
4
5pub fn track_raw_ptr<T: ?Sized>(
6    #[cfg_attr(not(feature = "track"), allow(unused_variables))] var_name: &str,
7    #[cfg_attr(not(feature = "track"), allow(unused_variables))] var_id: usize,
8    #[cfg_attr(not(feature = "track"), allow(unused_variables))] ptr_type: &str,
9    #[cfg_attr(not(feature = "track"), allow(unused_variables))] location: &str,
10    ptr: *const T,
11) -> *const T {
12    #[cfg(feature = "track")]
13    {
14        let mut tracker = TRACKER.lock();
15        tracker.record_raw_ptr_created(
16            var_name,
17            var_id,
18            ptr_type,
19            ptr as *const () as usize,
20            location,
21        );
22    }
23    ptr
24}
25
26/// Track mutable raw pointer creation.
27///
28/// Records a `RawPtrCreated` event. Use this when creating a `*mut T` pointer.
29///
30/// # Arguments
31///
32/// * `var_name` - Name for the pointer variable
33/// * `var_id` - Unique identifier
34/// * `ptr_type` - Type description (e.g., "*mut i32")
35/// * `location` - Source location
36/// * `ptr` - The raw pointer (returned unchanged)
37///
38/// # Returns
39///
40/// The input pointer, unchanged.
41///
42/// # Safety
43///
44/// This function is safe to call, but the pointer it tracks may be unsafe to dereference.
45#[inline(always)]
46pub fn track_raw_ptr_mut<T: ?Sized>(
47    #[cfg_attr(not(feature = "track"), allow(unused_variables))] var_name: &str,
48    #[cfg_attr(not(feature = "track"), allow(unused_variables))] var_id: usize,
49    #[cfg_attr(not(feature = "track"), allow(unused_variables))] ptr_type: &str,
50    #[cfg_attr(not(feature = "track"), allow(unused_variables))] location: &str,
51    ptr: *mut T,
52) -> *mut T {
53    #[cfg(feature = "track")]
54    {
55        let mut tracker = TRACKER.lock();
56        tracker.record_raw_ptr_created(
57            var_name,
58            var_id,
59            ptr_type,
60            ptr as *const () as usize,
61            location,
62        );
63    }
64    ptr
65}
66
67/// Track raw pointer dereference.
68///
69/// Records a `RawPtrDeref` event. Use this when dereferencing a raw pointer.
70///
71/// # Arguments
72///
73/// * `ptr_id` - Identifier of the pointer being dereferenced
74/// * `location` - Source location
75/// * `is_write` - `true` if writing through the pointer, `false` if reading
76#[inline(always)]
77pub fn track_raw_ptr_deref(
78    #[cfg_attr(not(feature = "track"), allow(unused_variables))] ptr_id: usize,
79    #[cfg_attr(not(feature = "track"), allow(unused_variables))] location: &str,
80    #[cfg_attr(not(feature = "track"), allow(unused_variables))] is_write: bool,
81) {
82    #[cfg(feature = "track")]
83    {
84        let mut tracker = TRACKER.lock();
85        tracker.record_raw_ptr_deref(ptr_id, location, is_write);
86    }
87}
88
89/// Track unsafe block entry.
90///
91/// Records an `UnsafeBlockEnter` event. Use this when entering an unsafe block.
92///
93/// # Arguments
94///
95/// * `block_id` - Unique identifier for this unsafe block
96/// * `location` - Source location
97#[inline(always)]
98pub fn track_unsafe_block_enter(
99    #[cfg_attr(not(feature = "track"), allow(unused_variables))] block_id: usize,
100    #[cfg_attr(not(feature = "track"), allow(unused_variables))] location: &str,
101) {
102    #[cfg(feature = "track")]
103    {
104        let mut tracker = TRACKER.lock();
105        tracker.record_unsafe_block_enter(block_id, location);
106    }
107}
108
109/// Track unsafe block exit.
110///
111/// Records an `UnsafeBlockExit` event. Use this when exiting an unsafe block.
112///
113/// # Arguments
114///
115/// * `block_id` - Identifier matching the corresponding `track_unsafe_block_enter`
116/// * `location` - Source location
117#[inline(always)]
118pub fn track_unsafe_block_exit(
119    #[cfg_attr(not(feature = "track"), allow(unused_variables))] block_id: usize,
120    #[cfg_attr(not(feature = "track"), allow(unused_variables))] location: &str,
121) {
122    #[cfg(feature = "track")]
123    {
124        let mut tracker = TRACKER.lock();
125        tracker.record_unsafe_block_exit(block_id, location);
126    }
127}
128
129/// Track unsafe function call.
130///
131/// Records an `UnsafeFnCall` event. Use this when calling an unsafe function.
132///
133/// # Arguments
134///
135/// * `fn_name` - Name of the unsafe function being called
136/// * `location` - Source location
137#[inline(always)]
138pub fn track_unsafe_fn_call(
139    #[cfg_attr(not(feature = "track"), allow(unused_variables))] fn_name: &str,
140    #[cfg_attr(not(feature = "track"), allow(unused_variables))] location: &str,
141) {
142    #[cfg(feature = "track")]
143    {
144        let mut tracker = TRACKER.lock();
145        tracker.record_unsafe_fn_call(fn_name, location);
146    }
147}
148
149/// Track FFI call.
150///
151/// Records an `FfiCall` event. Use this when calling a foreign function.
152///
153/// # Arguments
154///
155/// * `fn_name` - Name of the foreign function being called
156/// * `location` - Source location
157#[inline(always)]
158pub fn track_ffi_call(
159    #[cfg_attr(not(feature = "track"), allow(unused_variables))] fn_name: &str,
160    #[cfg_attr(not(feature = "track"), allow(unused_variables))] location: &str,
161) {
162    #[cfg(feature = "track")]
163    {
164        let mut tracker = TRACKER.lock();
165        tracker.record_ffi_call(fn_name, location);
166    }
167}
168
169/// Track transmute operation.
170///
171/// Records a `Transmute` event. Use this when using `std::mem::transmute`.
172///
173/// # Arguments
174///
175/// * `from_type` - Source type name
176/// * `to_type` - Destination type name
177/// * `location` - Source location
178#[inline(always)]
179pub fn track_transmute(
180    #[cfg_attr(not(feature = "track"), allow(unused_variables))] from_type: &str,
181    #[cfg_attr(not(feature = "track"), allow(unused_variables))] to_type: &str,
182    #[cfg_attr(not(feature = "track"), allow(unused_variables))] location: &str,
183) {
184    #[cfg(feature = "track")]
185    {
186        let mut tracker = TRACKER.lock();
187        tracker.record_transmute(from_type, to_type, location);
188    }
189}
190
191/// Track union field access.
192///
193/// Records a `UnionFieldAccess` event. Use this when accessing a union field.
194///
195/// # Arguments
196///
197/// * `union_name` - Name of the union
198/// * `field_name` - Name of the field being accessed
199/// * `location` - Source location
200#[inline(always)]
201pub fn track_union_field_access(
202    #[cfg_attr(not(feature = "track"), allow(unused_variables))] union_name: &str,
203    #[cfg_attr(not(feature = "track"), allow(unused_variables))] field_name: &str,
204    #[cfg_attr(not(feature = "track"), allow(unused_variables))] location: &str,
205) {
206    #[cfg(feature = "track")]
207    {
208        let mut tracker = TRACKER.lock();
209        tracker.record_union_field_access(union_name, field_name, location);
210    }
211}