1use std::error::Error;
3use std::fmt;
4use std::slice;
5
6pub unsafe fn copy_string<T: Copy>(
19 string: &[T],
20 buffer: *mut T,
21 length: usize,
22) -> Result<(), BufferOverflowError> {
23 let buffer = slice::from_raw_parts_mut(buffer, length);
24 if string.len() > buffer.len() {
25 return Err(BufferOverflowError {});
26 }
27
28 buffer[..string.len()].copy_from_slice(string);
29
30 Ok(())
31}
32
33#[derive(Debug)]
35pub struct BufferOverflowError {}
36
37impl fmt::Display for BufferOverflowError {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 write!(f, "BufferOverflowError")
40 }
41}
42
43impl Error for BufferOverflowError {
44 fn description(&self) -> &str {
45 "provided buffer is too small to copy the full contents of the data"
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use std::ffi::{CStr, CString};
52
53 use super::*;
54
55 #[test]
56 fn test_copy_string() {
57 let string = CString::new("foo").expect("Could not create CString");
58 let buffer: &mut [u8; 4] = &mut [0; 4];
59 let buffer_p = buffer.as_mut_ptr();
60
61 let bytes = string.to_bytes_with_nul();
62
63 unsafe {
64 match copy_string(&bytes, buffer_p, buffer.len()) {
65 Ok(_) => (),
66 Err(_e) => panic!("Failed to copy string to buffer"),
67 }
68 }
69
70 let result = CStr::from_bytes_with_nul(buffer).expect("Could not convert buffer to Cstr");
71 assert_eq!(string.as_c_str(), result)
72 }
73
74 #[test]
75 fn test_copy_string_buffer_overflow() {
76 let string = CString::new("foo").expect("Could not create CString");
77 let buffer: &mut [u8; 3] = &mut [0; 3];
78 let buffer_p = buffer.as_mut_ptr();
79
80 let bytes = string.to_bytes_with_nul();
81
82 unsafe {
83 if copy_string(&bytes, buffer_p, buffer.len()).is_ok() {
84 panic!("Failed to return an error due to a buffer overflow")
85 };
86 }
87 }
88}