Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions src/pam/converse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,13 @@ pub(super) unsafe extern "C" fn converse<C: Converser>(
response: *mut *mut pam_response,
appdata_ptr: *mut libc::c_void,
) -> libc::c_int {
let Ok(num_msg_usize) = usize::try_from(num_msg) else {
return PamErrorType::ConversationError.as_int();
};

let result = std::panic::catch_unwind(|| {
let mut resp_bufs = Vec::with_capacity(num_msg as usize);
for i in 0..num_msg as usize {
let mut resp_bufs = Vec::with_capacity(num_msg_usize);
for i in 0..num_msg_usize {
// convert the input messages to Rust types
// SAFETY: the PAM contract ensures that `num_msg` does not exceed the amount
// of messages presented to this function in `msg`, and that it is not being
Expand Down Expand Up @@ -226,7 +230,7 @@ pub(super) unsafe extern "C" fn converse<C: Converser>(
// or return a null pointer.
let temp_resp = unsafe {
libc::calloc(
num_msg as libc::size_t,
num_msg_usize,
std::mem::size_of::<pam_response>() as libc::size_t,
)
} as *mut pam_response;
Expand Down Expand Up @@ -438,4 +442,35 @@ mod test {

assert!(hello.panicked); // allowed now
}

#[test]
fn conversation_rejects_negative_message_count() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this test is prefix with miri_, it will also be run in the Miri test (I think that is possible and useful here)

let mut data = Box::pin(ConverserData {
converser: "tux".to_string(),
converser_name: "tux".to_string(),
no_interact: false,
auth_prompt: None,
timed_out: false,
panicked: false,
});
let cookie = PamConvBorrow::new(data.as_mut());
let pam_conv = cookie.borrow();

let mut raw_response = std::ptr::null_mut::<pam_response>();
let ret = unsafe {
pam_conv.conv.expect("non-null fn ptr")(
-1,
std::ptr::null_mut(),
&mut raw_response,
pam_conv.appdata_ptr,
)
};

assert_eq!(ret, PamErrorType::ConversationError.as_int());
assert!(raw_response.is_null());

let real_data =
unsafe { &*(pam_conv.appdata_ptr as *const ConverserData<String>) };
assert!(!real_data.panicked);
}
}
Loading