annotate src/pam_ffi/memory.rs @ 73:ac6881304c78

Do conversations, along with way too much stuff. This implements conversations, along with all the memory management brouhaha that goes along with it. The conversation now lives directly on the handle rather than being a thing you have to get from it and then call manually. It Turns Out this makes things a lot easier! I guess we reorganized things again. For the last time. For real. I promise. This all passes ASAN, so it seems Pretty Good!
author Paul Fisher <paul@pfish.zone>
date Thu, 05 Jun 2025 03:41:38 -0400
parents 47eb242a4f88
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
1 //! Things for dealing with memory.
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
2
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
3 use crate::ErrorCode;
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
4 use crate::Result;
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
5 use std::ffi::{c_char, c_void, CStr, CString};
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
6 use std::marker::{PhantomData, PhantomPinned};
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
7 use std::result::Result as StdResult;
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
8 use std::{ptr, slice};
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
9
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
10 /// Makes whatever it's in not [`Send`], [`Sync`], or [`Unpin`].
73
ac6881304c78 Do conversations, along with way too much stuff.
Paul Fisher <paul@pfish.zone>
parents: 72
diff changeset
11 #[repr(C)]
ac6881304c78 Do conversations, along with way too much stuff.
Paul Fisher <paul@pfish.zone>
parents: 72
diff changeset
12 #[derive(Debug)]
ac6881304c78 Do conversations, along with way too much stuff.
Paul Fisher <paul@pfish.zone>
parents: 72
diff changeset
13 pub struct Immovable(pub PhantomData<(*mut u8, PhantomPinned)>);
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
14
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
15 /// Safely converts a `&str` option to a `CString` option.
64
bbe84835d6db More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents: 60
diff changeset
16 pub fn option_cstr(prompt: Option<&str>) -> Result<Option<CString>> {
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
17 prompt
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
18 .map(CString::new)
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
19 .transpose()
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
20 .map_err(|_| ErrorCode::ConversationError)
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
21 }
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
22
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
23 /// Gets the pointer to the given CString, or a null pointer if absent.
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
24 pub fn prompt_ptr(prompt: Option<&CString>) -> *const c_char {
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
25 match prompt {
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
26 Some(c_str) => c_str.as_ptr(),
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
27 None => ptr::null(),
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
28 }
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
29 }
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
30
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
31 /// Creates an owned copy of a string that is returned from a
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
32 /// <code>pam_get_<var>whatever</var></code> function.
72
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
33 ///
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
34 /// # Safety
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
35 ///
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
36 /// It's on you to provide a valid string.
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
37 pub unsafe fn copy_pam_string(result_ptr: *const libc::c_char) -> Result<String> {
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
38 // We really shouldn't get a null pointer back here, but if we do, return nothing.
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
39 if result_ptr.is_null() {
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
40 return Ok(String::new());
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
41 }
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
42 let bytes = unsafe { CStr::from_ptr(result_ptr) };
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
43 bytes
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
44 .to_str()
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
45 .map(String::from)
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
46 .map_err(|_| ErrorCode::ConversationError)
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
47 }
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
48
72
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
49 /// Wraps a string returned from PAM as an `Option<&str>`.
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
50 pub unsafe fn wrap_string<'a>(data: *const libc::c_char) -> Result<Option<&'a str>> {
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
51 let ret = if data.is_null() {
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
52 None
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
53 } else {
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
54 Some(
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
55 CStr::from_ptr(data)
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
56 .to_str()
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
57 .map_err(|_| ErrorCode::ConversationError)?,
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
58 )
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
59 };
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
60 Ok(ret)
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
61 }
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
62
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
63 /// Allocates a string with the given contents on the C heap.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
64 ///
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
65 /// This is like [`CString::new`](std::ffi::CString::new), but:
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
66 ///
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
67 /// - it allocates data on the C heap with [`libc::malloc`].
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
68 /// - it doesn't take ownership of the data passed in.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
69 pub fn malloc_str(text: impl AsRef<str>) -> StdResult<*mut c_char, NulError> {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
70 let data = text.as_ref().as_bytes();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
71 if let Some(nul) = data.iter().position(|x| *x == 0) {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
72 return Err(NulError(nul));
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
73 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
74 unsafe {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
75 let data_alloc = libc::calloc(data.len() + 1, 1);
73
ac6881304c78 Do conversations, along with way too much stuff.
Paul Fisher <paul@pfish.zone>
parents: 72
diff changeset
76 libc::memcpy(data_alloc, data.as_ptr().cast(), data.len());
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
77 Ok(data_alloc.cast())
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
78 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
79 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
80
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
81 /// Writes zeroes over the contents of a C string.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
82 ///
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
83 /// This won't overwrite a null pointer.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
84 ///
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
85 /// # Safety
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
86 ///
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
87 /// It's up to you to provide a valid C string.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
88 pub unsafe fn zero_c_string(cstr: *mut c_void) {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
89 if !cstr.is_null() {
73
ac6881304c78 Do conversations, along with way too much stuff.
Paul Fisher <paul@pfish.zone>
parents: 72
diff changeset
90 libc::memset(cstr, 0, libc::strlen(cstr.cast()));
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
91 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
92 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
93
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
94 /// Binary data used in requests and responses.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
95 ///
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
96 /// This is an unsized data type whose memory goes beyond its data.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
97 /// This must be allocated on the C heap.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
98 ///
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
99 /// A Linux-PAM extension.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
100 #[repr(C)]
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
101 pub struct CBinaryData {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
102 /// The total length of the structure; a u32 in network byte order (BE).
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
103 total_length: [u8; 4],
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
104 /// A tag of undefined meaning.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
105 data_type: u8,
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
106 /// Pointer to an array of length [`length`](Self::length) − 5
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
107 data: [u8; 0],
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
108 _marker: Immovable,
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
109 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
110
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
111 impl CBinaryData {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
112 /// Copies the given data to a new BinaryData on the heap.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
113 pub fn alloc(source: &[u8], data_type: u8) -> StdResult<*mut CBinaryData, TooBigError> {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
114 let buffer_size = u32::try_from(source.len() + 5).map_err(|_| TooBigError {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
115 max: (u32::MAX - 5) as usize,
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
116 actual: source.len(),
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
117 })?;
73
ac6881304c78 Do conversations, along with way too much stuff.
Paul Fisher <paul@pfish.zone>
parents: 72
diff changeset
118 // SAFETY: We're only allocating here.
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
119 let data = unsafe {
73
ac6881304c78 Do conversations, along with way too much stuff.
Paul Fisher <paul@pfish.zone>
parents: 72
diff changeset
120 let dest_buffer: *mut CBinaryData = libc::malloc(buffer_size as usize).cast();
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
121 let data = &mut *dest_buffer;
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
122 data.total_length = buffer_size.to_be_bytes();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
123 data.data_type = data_type;
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
124 let dest = data.data.as_mut_ptr();
73
ac6881304c78 Do conversations, along with way too much stuff.
Paul Fisher <paul@pfish.zone>
parents: 72
diff changeset
125 libc::memcpy(dest.cast(), source.as_ptr().cast(), source.len());
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
126 dest_buffer
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
127 };
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
128 Ok(data)
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
129 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
130
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
131 fn length(&self) -> usize {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
132 u32::from_be_bytes(self.total_length).saturating_sub(5) as usize
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
133 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
134
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
135 pub fn contents(&self) -> &[u8] {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
136 unsafe { slice::from_raw_parts(self.data.as_ptr(), self.length()) }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
137 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
138 pub fn data_type(&self) -> u8 {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
139 self.data_type
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
140 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
141
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
142 /// Clears this data and frees it.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
143 pub unsafe fn zero_contents(&mut self) {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
144 let contents = slice::from_raw_parts_mut(self.data.as_mut_ptr(), self.length());
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
145 for v in contents {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
146 *v = 0
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
147 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
148 self.data_type = 0;
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
149 self.total_length = [0; 4];
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
150 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
151 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
152
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
153 #[derive(Debug, thiserror::Error)]
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
154 #[error("null byte within input at byte {0}")]
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
155 pub struct NulError(pub usize);
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
156
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
157 /// Returned when trying to fit too much data into a binary message.
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
158 #[derive(Debug, thiserror::Error)]
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
159 #[error("cannot create a message of {actual} bytes; maximum is {max}")]
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
160 pub struct TooBigError {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
161 pub actual: usize,
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
162 pub max: usize,
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
163 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
164
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
165 #[cfg(test)]
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
166 mod tests {
72
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
167 use super::{copy_pam_string, malloc_str, option_cstr, prompt_ptr, zero_c_string};
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
168 use crate::ErrorCode;
72
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
169 use std::ffi::CString;
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
170 #[test]
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
171 fn test_strings() {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
172 let str = malloc_str("hello there").unwrap();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
173 malloc_str("hell\0 there").unwrap_err();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
174 unsafe {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
175 let copied = copy_pam_string(str.cast()).unwrap();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
176 assert_eq!("hello there", copied);
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
177 zero_c_string(str.cast());
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
178 let idx_three = str.add(3).as_mut().unwrap();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
179 *idx_three = 0x80u8 as i8;
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
180 let zeroed = copy_pam_string(str.cast()).unwrap();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
181 assert!(zeroed.is_empty());
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
182 libc::free(str.cast());
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
183 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
184 }
72
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
185
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
186 #[test]
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
187 fn test_option_str() {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
188 let good = option_cstr(Some("whatever")).unwrap();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
189 assert_eq!("whatever", good.unwrap().to_str().unwrap());
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
190 let no_str = option_cstr(None).unwrap();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
191 assert!(no_str.is_none());
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
192 let bad_str = option_cstr(Some("what\0ever")).unwrap_err();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
193 assert_eq!(ErrorCode::ConversationError, bad_str);
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
194 }
72
47eb242a4f88 Fill out the PamHandle trait.
Paul Fisher <paul@pfish.zone>
parents: 71
diff changeset
195
71
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
196 #[test]
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
197 fn test_prompt() {
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
198 let prompt_cstr = CString::new("good").ok();
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
199 let prompt = prompt_ptr(prompt_cstr.as_ref());
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
200 assert!(!prompt.is_null());
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
201 let no_prompt = prompt_ptr(None);
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
202 assert!(no_prompt.is_null());
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
203 }
58f9d2a4df38 Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
204 }