Coverage Report

Created: 2025-10-29 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/openssl-0.10.62/src/stack.rs
Line
Count
Source
1
use cfg_if::cfg_if;
2
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
3
use libc::c_int;
4
use std::borrow::Borrow;
5
use std::convert::AsRef;
6
use std::fmt;
7
use std::iter;
8
use std::marker::PhantomData;
9
use std::mem;
10
use std::ops::{Deref, DerefMut, Index, IndexMut, Range};
11
12
use crate::error::ErrorStack;
13
use crate::util::ForeignTypeExt;
14
use crate::{cvt, cvt_p, LenType};
15
16
cfg_if! {
17
    if #[cfg(ossl110)] {
18
        use ffi::{
19
            OPENSSL_sk_pop, OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_value, OPENSSL_STACK,
20
            OPENSSL_sk_new_null, OPENSSL_sk_push,
21
        };
22
    } else {
23
        use ffi::{
24
            sk_pop as OPENSSL_sk_pop, sk_free as OPENSSL_sk_free, sk_num as OPENSSL_sk_num,
25
            sk_value as OPENSSL_sk_value, _STACK as OPENSSL_STACK,
26
            sk_new_null as OPENSSL_sk_new_null, sk_push as OPENSSL_sk_push,
27
        };
28
    }
29
}
30
31
/// Trait implemented by types which can be placed in a stack.
32
///
33
/// It should not be implemented for any type outside of this crate.
34
pub trait Stackable: ForeignType {
35
    /// The C stack type for this element.
36
    ///
37
    /// Generally called `stack_st_{ELEMENT_TYPE}`, normally hidden by the
38
    /// `STACK_OF(ELEMENT_TYPE)` macro in the OpenSSL API.
39
    type StackType;
40
}
41
42
/// An owned stack of `T`.
43
pub struct Stack<T: Stackable>(*mut T::StackType);
44
45
unsafe impl<T: Stackable + Send> Send for Stack<T> {}
46
unsafe impl<T: Stackable + Sync> Sync for Stack<T> {}
47
48
impl<T> fmt::Debug for Stack<T>
49
where
50
    T: Stackable,
51
    T::Ref: fmt::Debug,
52
{
53
0
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
54
0
        fmt.debug_list().entries(self).finish()
55
0
    }
56
}
57
impl<T: Stackable> Drop for Stack<T> {
58
0
    fn drop(&mut self) {
59
        unsafe {
60
0
            while self.pop().is_some() {}
61
0
            OPENSSL_sk_free(self.0 as *mut _);
62
        }
63
0
    }
Unexecuted instantiation: <openssl::stack::Stack<openssl::asn1::Asn1Object> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::GeneralName> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::X509> as core::ops::drop::Drop>::drop
64
}
65
66
impl<T: Stackable> Stack<T> {
67
0
    pub fn new() -> Result<Stack<T>, ErrorStack> {
68
        unsafe {
69
0
            ffi::init();
70
0
            let ptr = cvt_p(OPENSSL_sk_new_null())?;
71
0
            Ok(Stack(ptr as *mut _))
72
        }
73
0
    }
Unexecuted instantiation: <openssl::stack::Stack<openssl::asn1::Asn1Object>>::new
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::GeneralName>>::new
74
}
75
76
impl<T: Stackable> iter::IntoIterator for Stack<T> {
77
    type IntoIter = IntoIter<T>;
78
    type Item = T;
79
80
0
    fn into_iter(self) -> IntoIter<T> {
81
0
        let it = IntoIter {
82
0
            stack: self.0,
83
0
            idxs: 0..self.len() as LenType,
84
0
        };
85
0
        mem::forget(self);
86
0
        it
87
0
    }
88
}
89
90
impl<T: Stackable> AsRef<StackRef<T>> for Stack<T> {
91
0
    fn as_ref(&self) -> &StackRef<T> {
92
0
        self
93
0
    }
94
}
95
96
impl<T: Stackable> Borrow<StackRef<T>> for Stack<T> {
97
0
    fn borrow(&self) -> &StackRef<T> {
98
0
        self
99
0
    }
100
}
101
102
impl<T: Stackable> ForeignType for Stack<T> {
103
    type CType = T::StackType;
104
    type Ref = StackRef<T>;
105
106
    #[inline]
107
0
    unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack<T> {
108
0
        assert!(
109
0
            !ptr.is_null(),
110
            "Must not instantiate a Stack from a null-ptr - use Stack::new() in \
111
             that case"
112
        );
113
0
        Stack(ptr)
114
0
    }
Unexecuted instantiation: <openssl::stack::Stack<openssl::ssl::SslCipher> as foreign_types_shared::ForeignType>::from_ptr
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::GeneralName> as foreign_types_shared::ForeignType>::from_ptr
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::X509Extension> as foreign_types_shared::ForeignType>::from_ptr
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::AccessDescription> as foreign_types_shared::ForeignType>::from_ptr
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::DistPoint> as foreign_types_shared::ForeignType>::from_ptr
Unexecuted instantiation: <openssl::stack::Stack<openssl::string::OpensslString> as foreign_types_shared::ForeignType>::from_ptr
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::X509> as foreign_types_shared::ForeignType>::from_ptr
115
116
    #[inline]
117
0
    fn as_ptr(&self) -> *mut T::StackType {
118
0
        self.0
119
0
    }
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::X509Name> as foreign_types_shared::ForeignType>::as_ptr
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::X509> as foreign_types_shared::ForeignType>::as_ptr
Unexecuted instantiation: <openssl::stack::Stack<openssl::asn1::Asn1Object> as foreign_types_shared::ForeignType>::as_ptr
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::GeneralName> as foreign_types_shared::ForeignType>::as_ptr
120
}
121
122
impl<T: Stackable> Deref for Stack<T> {
123
    type Target = StackRef<T>;
124
125
0
    fn deref(&self) -> &StackRef<T> {
126
0
        unsafe { StackRef::from_ptr(self.0) }
127
0
    }
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::X509> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::GeneralName> as core::ops::deref::Deref>::deref
128
}
129
130
impl<T: Stackable> DerefMut for Stack<T> {
131
0
    fn deref_mut(&mut self) -> &mut StackRef<T> {
132
0
        unsafe { StackRef::from_ptr_mut(self.0) }
133
0
    }
Unexecuted instantiation: <openssl::stack::Stack<openssl::asn1::Asn1Object> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::GeneralName> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <openssl::stack::Stack<openssl::x509::X509> as core::ops::deref::DerefMut>::deref_mut
134
}
135
136
pub struct IntoIter<T: Stackable> {
137
    stack: *mut T::StackType,
138
    idxs: Range<LenType>,
139
}
140
141
impl<T: Stackable> Drop for IntoIter<T> {
142
0
    fn drop(&mut self) {
143
        unsafe {
144
            // https://github.com/rust-lang/rust-clippy/issues/7510
145
            #[allow(clippy::while_let_on_iterator)]
146
0
            while let Some(_) = self.next() {}
147
0
            OPENSSL_sk_free(self.stack as *mut _);
148
        }
149
0
    }
150
}
151
152
impl<T: Stackable> Iterator for IntoIter<T> {
153
    type Item = T;
154
155
0
    fn next(&mut self) -> Option<T> {
156
        unsafe {
157
0
            self.idxs
158
0
                .next()
159
0
                .map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
160
        }
161
0
    }
162
163
0
    fn size_hint(&self) -> (usize, Option<usize>) {
164
0
        self.idxs.size_hint()
165
0
    }
166
}
167
168
impl<T: Stackable> DoubleEndedIterator for IntoIter<T> {
169
0
    fn next_back(&mut self) -> Option<T> {
170
        unsafe {
171
0
            self.idxs
172
0
                .next_back()
173
0
                .map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
174
        }
175
0
    }
176
}
177
178
impl<T: Stackable> ExactSizeIterator for IntoIter<T> {}
179
180
pub struct StackRef<T: Stackable>(Opaque, PhantomData<T>);
181
182
unsafe impl<T: Stackable + Send> Send for StackRef<T> {}
183
unsafe impl<T: Stackable + Sync> Sync for StackRef<T> {}
184
185
impl<T: Stackable> ForeignTypeRef for StackRef<T> {
186
    type CType = T::StackType;
187
}
188
189
impl<T: Stackable> StackRef<T> {
190
0
    fn as_stack(&self) -> *mut OPENSSL_STACK {
191
0
        self.as_ptr() as *mut _
192
0
    }
Unexecuted instantiation: <openssl::stack::StackRef<openssl::asn1::Asn1Object>>::as_stack
Unexecuted instantiation: <openssl::stack::StackRef<openssl::x509::GeneralName>>::as_stack
Unexecuted instantiation: <openssl::stack::StackRef<openssl::x509::X509>>::as_stack
193
194
    /// Returns the number of items in the stack.
195
0
    pub fn len(&self) -> usize {
196
0
        unsafe { OPENSSL_sk_num(self.as_stack()) as usize }
197
0
    }
Unexecuted instantiation: <openssl::stack::StackRef<openssl::x509::X509>>::len
Unexecuted instantiation: <openssl::stack::StackRef<openssl::x509::GeneralName>>::len
198
199
    /// Determines if the stack is empty.
200
0
    pub fn is_empty(&self) -> bool {
201
0
        self.len() == 0
202
0
    }
203
204
0
    pub fn iter(&self) -> Iter<'_, T> {
205
0
        Iter {
206
0
            stack: self,
207
0
            idxs: 0..self.len() as LenType,
208
0
        }
209
0
    }
Unexecuted instantiation: <openssl::stack::StackRef<openssl::x509::X509>>::iter
Unexecuted instantiation: <openssl::stack::StackRef<openssl::x509::GeneralName>>::iter
210
211
0
    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
212
0
        IterMut {
213
0
            idxs: 0..self.len() as LenType,
214
0
            stack: self,
215
0
        }
216
0
    }
217
218
    /// Returns a reference to the element at the given index in the
219
    /// stack or `None` if the index is out of bounds
220
0
    pub fn get(&self, idx: usize) -> Option<&T::Ref> {
221
        unsafe {
222
0
            if idx >= self.len() {
223
0
                return None;
224
0
            }
225
226
0
            Some(T::Ref::from_ptr(self._get(idx)))
227
        }
228
0
    }
229
230
    /// Returns a mutable reference to the element at the given index in the
231
    /// stack or `None` if the index is out of bounds
232
0
    pub fn get_mut(&mut self, idx: usize) -> Option<&mut T::Ref> {
233
        unsafe {
234
0
            if idx >= self.len() {
235
0
                return None;
236
0
            }
237
238
0
            Some(T::Ref::from_ptr_mut(self._get(idx)))
239
        }
240
0
    }
241
242
    /// Pushes a value onto the top of the stack.
243
0
    pub fn push(&mut self, data: T) -> Result<(), ErrorStack> {
244
        unsafe {
245
0
            cvt(OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _) as c_int)?;
246
0
            mem::forget(data);
247
0
            Ok(())
248
        }
249
0
    }
Unexecuted instantiation: <openssl::stack::StackRef<openssl::asn1::Asn1Object>>::push
Unexecuted instantiation: <openssl::stack::StackRef<openssl::x509::GeneralName>>::push
250
251
    /// Removes the last element from the stack and returns it.
252
0
    pub fn pop(&mut self) -> Option<T> {
253
        unsafe {
254
0
            let ptr = OPENSSL_sk_pop(self.as_stack());
255
0
            T::from_ptr_opt(ptr as *mut _)
256
        }
257
0
    }
Unexecuted instantiation: <openssl::stack::StackRef<openssl::asn1::Asn1Object>>::pop
Unexecuted instantiation: <openssl::stack::StackRef<openssl::x509::GeneralName>>::pop
Unexecuted instantiation: <openssl::stack::StackRef<openssl::x509::X509>>::pop
258
259
0
    unsafe fn _get(&self, idx: usize) -> *mut T::CType {
260
0
        OPENSSL_sk_value(self.as_stack(), idx as LenType) as *mut _
261
0
    }
262
}
263
264
impl<T: Stackable> Index<usize> for StackRef<T> {
265
    type Output = T::Ref;
266
267
0
    fn index(&self, index: usize) -> &T::Ref {
268
0
        self.get(index).unwrap()
269
0
    }
270
}
271
272
impl<T: Stackable> IndexMut<usize> for StackRef<T> {
273
0
    fn index_mut(&mut self, index: usize) -> &mut T::Ref {
274
0
        self.get_mut(index).unwrap()
275
0
    }
276
}
277
278
impl<'a, T: Stackable> iter::IntoIterator for &'a StackRef<T> {
279
    type Item = &'a T::Ref;
280
    type IntoIter = Iter<'a, T>;
281
282
0
    fn into_iter(self) -> Iter<'a, T> {
283
0
        self.iter()
284
0
    }
285
}
286
287
impl<'a, T: Stackable> iter::IntoIterator for &'a mut StackRef<T> {
288
    type Item = &'a mut T::Ref;
289
    type IntoIter = IterMut<'a, T>;
290
291
0
    fn into_iter(self) -> IterMut<'a, T> {
292
0
        self.iter_mut()
293
0
    }
294
}
295
296
impl<'a, T: Stackable> iter::IntoIterator for &'a Stack<T> {
297
    type Item = &'a T::Ref;
298
    type IntoIter = Iter<'a, T>;
299
300
0
    fn into_iter(self) -> Iter<'a, T> {
301
0
        self.iter()
302
0
    }
Unexecuted instantiation: <&openssl::stack::Stack<openssl::x509::X509> as core::iter::traits::collect::IntoIterator>::into_iter
Unexecuted instantiation: <&openssl::stack::Stack<openssl::x509::GeneralName> as core::iter::traits::collect::IntoIterator>::into_iter
303
}
304
305
impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack<T> {
306
    type Item = &'a mut T::Ref;
307
    type IntoIter = IterMut<'a, T>;
308
309
0
    fn into_iter(self) -> IterMut<'a, T> {
310
0
        self.iter_mut()
311
0
    }
312
}
313
314
/// An iterator over the stack's contents.
315
pub struct Iter<'a, T: Stackable> {
316
    stack: &'a StackRef<T>,
317
    idxs: Range<LenType>,
318
}
319
320
impl<'a, T: Stackable> Iterator for Iter<'a, T> {
321
    type Item = &'a T::Ref;
322
323
0
    fn next(&mut self) -> Option<&'a T::Ref> {
324
        unsafe {
325
0
            self.idxs
326
0
                .next()
327
0
                .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
Unexecuted instantiation: <openssl::stack::Iter<openssl::x509::GeneralName> as core::iter::traits::iterator::Iterator>::next::{closure#0}
Unexecuted instantiation: <openssl::stack::Iter<openssl::x509::X509> as core::iter::traits::iterator::Iterator>::next::{closure#0}
328
        }
329
0
    }
Unexecuted instantiation: <openssl::stack::Iter<openssl::x509::GeneralName> as core::iter::traits::iterator::Iterator>::next
Unexecuted instantiation: <openssl::stack::Iter<openssl::x509::X509> as core::iter::traits::iterator::Iterator>::next
330
331
0
    fn size_hint(&self) -> (usize, Option<usize>) {
332
0
        self.idxs.size_hint()
333
0
    }
334
}
335
336
impl<'a, T: Stackable> DoubleEndedIterator for Iter<'a, T> {
337
0
    fn next_back(&mut self) -> Option<&'a T::Ref> {
338
        unsafe {
339
0
            self.idxs
340
0
                .next_back()
341
0
                .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
342
        }
343
0
    }
344
}
345
346
impl<'a, T: Stackable> ExactSizeIterator for Iter<'a, T> {}
347
348
/// A mutable iterator over the stack's contents.
349
pub struct IterMut<'a, T: Stackable> {
350
    stack: &'a mut StackRef<T>,
351
    idxs: Range<LenType>,
352
}
353
354
impl<'a, T: Stackable> Iterator for IterMut<'a, T> {
355
    type Item = &'a mut T::Ref;
356
357
0
    fn next(&mut self) -> Option<&'a mut T::Ref> {
358
        unsafe {
359
0
            self.idxs
360
0
                .next()
361
0
                .map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
362
        }
363
0
    }
364
365
0
    fn size_hint(&self) -> (usize, Option<usize>) {
366
0
        self.idxs.size_hint()
367
0
    }
368
}
369
370
impl<'a, T: Stackable> DoubleEndedIterator for IterMut<'a, T> {
371
0
    fn next_back(&mut self) -> Option<&'a mut T::Ref> {
372
        unsafe {
373
0
            self.idxs
374
0
                .next_back()
375
0
                .map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
376
        }
377
0
    }
378
}
379
380
impl<'a, T: Stackable> ExactSizeIterator for IterMut<'a, T> {}