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};
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 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result53     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
54         fmt.debug_list().entries(self).finish()
55     }
56 }
57 impl<T: Stackable> Drop for Stack<T> {
drop(&mut self)58     fn drop(&mut self) {
59         unsafe {
60             while self.pop().is_some() {}
61             OPENSSL_sk_free(self.0 as *mut _);
62         }
63     }
64 }
65 
66 impl<T: Stackable> Stack<T> {
new() -> Result<Stack<T>, ErrorStack>67     pub fn new() -> Result<Stack<T>, ErrorStack> {
68         unsafe {
69             ffi::init();
70             let ptr = cvt_p(OPENSSL_sk_new_null())?;
71             Ok(Stack(ptr as *mut _))
72         }
73     }
74 }
75 
76 impl<T: Stackable> iter::IntoIterator for Stack<T> {
77     type IntoIter = IntoIter<T>;
78     type Item = T;
79 
into_iter(self) -> IntoIter<T>80     fn into_iter(self) -> IntoIter<T> {
81         let it = IntoIter {
82             stack: self.0,
83             idxs: 0..self.len() as c_int,
84         };
85         mem::forget(self);
86         it
87     }
88 }
89 
90 impl<T: Stackable> AsRef<StackRef<T>> for Stack<T> {
as_ref(&self) -> &StackRef<T>91     fn as_ref(&self) -> &StackRef<T> {
92         &*self
93     }
94 }
95 
96 impl<T: Stackable> Borrow<StackRef<T>> for Stack<T> {
borrow(&self) -> &StackRef<T>97     fn borrow(&self) -> &StackRef<T> {
98         &*self
99     }
100 }
101 
102 impl<T: Stackable> ForeignType for Stack<T> {
103     type CType = T::StackType;
104     type Ref = StackRef<T>;
105 
106     #[inline]
from_ptr(ptr: *mut T::StackType) -> Stack<T>107     unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack<T> {
108         assert!(
109             !ptr.is_null(),
110             "Must not instantiate a Stack from a null-ptr - use Stack::new() in \
111              that case"
112         );
113         Stack(ptr)
114     }
115 
116     #[inline]
as_ptr(&self) -> *mut T::StackType117     fn as_ptr(&self) -> *mut T::StackType {
118         self.0
119     }
120 }
121 
122 impl<T: Stackable> Deref for Stack<T> {
123     type Target = StackRef<T>;
124 
deref(&self) -> &StackRef<T>125     fn deref(&self) -> &StackRef<T> {
126         unsafe { StackRef::from_ptr(self.0) }
127     }
128 }
129 
130 impl<T: Stackable> DerefMut for Stack<T> {
deref_mut(&mut self) -> &mut StackRef<T>131     fn deref_mut(&mut self) -> &mut StackRef<T> {
132         unsafe { StackRef::from_ptr_mut(self.0) }
133     }
134 }
135 
136 pub struct IntoIter<T: Stackable> {
137     stack: *mut T::StackType,
138     idxs: Range<c_int>,
139 }
140 
141 impl<T: Stackable> Drop for IntoIter<T> {
drop(&mut self)142     fn drop(&mut self) {
143         unsafe {
144             // https://github.com/rust-lang/rust-clippy/issues/7510
145             #[allow(clippy::while_let_on_iterator)]
146             while let Some(_) = self.next() {}
147             OPENSSL_sk_free(self.stack as *mut _);
148         }
149     }
150 }
151 
152 impl<T: Stackable> Iterator for IntoIter<T> {
153     type Item = T;
154 
next(&mut self) -> Option<T>155     fn next(&mut self) -> Option<T> {
156         unsafe {
157             self.idxs
158                 .next()
159                 .map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
160         }
161     }
162 
size_hint(&self) -> (usize, Option<usize>)163     fn size_hint(&self) -> (usize, Option<usize>) {
164         self.idxs.size_hint()
165     }
166 }
167 
168 impl<T: Stackable> DoubleEndedIterator for IntoIter<T> {
next_back(&mut self) -> Option<T>169     fn next_back(&mut self) -> Option<T> {
170         unsafe {
171             self.idxs
172                 .next_back()
173                 .map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
174         }
175     }
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> {
as_stack(&self) -> *mut OPENSSL_STACK190     fn as_stack(&self) -> *mut OPENSSL_STACK {
191         self.as_ptr() as *mut _
192     }
193 
194     /// Returns the number of items in the stack.
len(&self) -> usize195     pub fn len(&self) -> usize {
196         unsafe { OPENSSL_sk_num(self.as_stack()) as usize }
197     }
198 
199     /// Determines if the stack is empty.
is_empty(&self) -> bool200     pub fn is_empty(&self) -> bool {
201         self.len() == 0
202     }
203 
iter(&self) -> Iter<'_, T>204     pub fn iter(&self) -> Iter<'_, T> {
205         Iter {
206             stack: self,
207             idxs: 0..self.len() as c_int,
208         }
209     }
210 
iter_mut(&mut self) -> IterMut<'_, T>211     pub fn iter_mut(&mut self) -> IterMut<'_, T> {
212         IterMut {
213             idxs: 0..self.len() as c_int,
214             stack: self,
215         }
216     }
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
get(&self, idx: usize) -> Option<&T::Ref>220     pub fn get(&self, idx: usize) -> Option<&T::Ref> {
221         unsafe {
222             if idx >= self.len() {
223                 return None;
224             }
225 
226             Some(T::Ref::from_ptr(self._get(idx)))
227         }
228     }
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
get_mut(&mut self, idx: usize) -> Option<&mut T::Ref>232     pub fn get_mut(&mut self, idx: usize) -> Option<&mut T::Ref> {
233         unsafe {
234             if idx >= self.len() {
235                 return None;
236             }
237 
238             Some(T::Ref::from_ptr_mut(self._get(idx)))
239         }
240     }
241 
242     /// Pushes a value onto the top of the stack.
push(&mut self, data: T) -> Result<(), ErrorStack>243     pub fn push(&mut self, data: T) -> Result<(), ErrorStack> {
244         unsafe {
245             cvt(OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _))?;
246             mem::forget(data);
247             Ok(())
248         }
249     }
250 
251     /// Removes the last element from the stack and returns it.
pop(&mut self) -> Option<T>252     pub fn pop(&mut self) -> Option<T> {
253         unsafe {
254             let ptr = OPENSSL_sk_pop(self.as_stack());
255             T::from_ptr_opt(ptr as *mut _)
256         }
257     }
258 
_get(&self, idx: usize) -> *mut T::CType259     unsafe fn _get(&self, idx: usize) -> *mut T::CType {
260         OPENSSL_sk_value(self.as_stack(), idx as c_int) as *mut _
261     }
262 }
263 
264 impl<T: Stackable> Index<usize> for StackRef<T> {
265     type Output = T::Ref;
266 
index(&self, index: usize) -> &T::Ref267     fn index(&self, index: usize) -> &T::Ref {
268         self.get(index).unwrap()
269     }
270 }
271 
272 impl<T: Stackable> IndexMut<usize> for StackRef<T> {
index_mut(&mut self, index: usize) -> &mut T::Ref273     fn index_mut(&mut self, index: usize) -> &mut T::Ref {
274         self.get_mut(index).unwrap()
275     }
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 
into_iter(self) -> Iter<'a, T>282     fn into_iter(self) -> Iter<'a, T> {
283         self.iter()
284     }
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 
into_iter(self) -> IterMut<'a, T>291     fn into_iter(self) -> IterMut<'a, T> {
292         self.iter_mut()
293     }
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 
into_iter(self) -> Iter<'a, T>300     fn into_iter(self) -> Iter<'a, T> {
301         self.iter()
302     }
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 
into_iter(self) -> IterMut<'a, T>309     fn into_iter(self) -> IterMut<'a, T> {
310         self.iter_mut()
311     }
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<c_int>,
318 }
319 
320 impl<'a, T: Stackable> Iterator for Iter<'a, T> {
321     type Item = &'a T::Ref;
322 
next(&mut self) -> Option<&'a T::Ref>323     fn next(&mut self) -> Option<&'a T::Ref> {
324         unsafe {
325             self.idxs
326                 .next()
327                 .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
328         }
329     }
330 
size_hint(&self) -> (usize, Option<usize>)331     fn size_hint(&self) -> (usize, Option<usize>) {
332         self.idxs.size_hint()
333     }
334 }
335 
336 impl<'a, T: Stackable> DoubleEndedIterator for Iter<'a, T> {
next_back(&mut self) -> Option<&'a T::Ref>337     fn next_back(&mut self) -> Option<&'a T::Ref> {
338         unsafe {
339             self.idxs
340                 .next_back()
341                 .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
342         }
343     }
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<c_int>,
352 }
353 
354 impl<'a, T: Stackable> Iterator for IterMut<'a, T> {
355     type Item = &'a mut T::Ref;
356 
next(&mut self) -> Option<&'a mut T::Ref>357     fn next(&mut self) -> Option<&'a mut T::Ref> {
358         unsafe {
359             self.idxs
360                 .next()
361                 .map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
362         }
363     }
364 
size_hint(&self) -> (usize, Option<usize>)365     fn size_hint(&self) -> (usize, Option<usize>) {
366         self.idxs.size_hint()
367     }
368 }
369 
370 impl<'a, T: Stackable> DoubleEndedIterator for IterMut<'a, T> {
next_back(&mut self) -> Option<&'a mut T::Ref>371     fn next_back(&mut self) -> Option<&'a mut T::Ref> {
372         unsafe {
373             self.idxs
374                 .next_back()
375                 .map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
376         }
377     }
378 }
379 
380 impl<'a, T: Stackable> ExactSizeIterator for IterMut<'a, T> {}
381