Coverage Report

Created: 2026-03-31 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata/rust/src/ffi/strings.rs
Line
Count
Source
1
/* Copyright (C) 2023 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
use std::ffi::CString;
19
use std::os::raw::c_char;
20
21
/// FFI utility function to copy a Rust string to a C string buffer.
22
///
23
/// Return true on success. On error, false will be returned.
24
///
25
/// An error will be returned if the provided string cannot be
26
/// converted to a C string (for example, it contains NULs), or if the
27
/// provided buffer is not large enough.
28
///
29
/// # Safety
30
///
31
/// Unsafe as this depends on the caller providing valid buf and size
32
/// parameters.
33
12.0k
pub unsafe fn copy_to_c_char(src: String, buf: *mut c_char, size: usize) -> bool {
34
12.0k
    if let Ok(src) = CString::new(src) {
35
12.0k
        let src = src.as_bytes_with_nul();
36
12.0k
        if size >= src.len() {
37
12.0k
            let buf = std::slice::from_raw_parts_mut(buf as *mut u8, size);
38
12.0k
            buf[0..src.len()].copy_from_slice(src);
39
12.0k
            return true;
40
0
        }
41
0
    }
42
0
    false
43
12.0k
}
44
45
#[cfg(test)]
46
mod test {
47
    use super::*;
48
49
    #[test]
50
    fn test_copy_to_c_char() {
51
        unsafe {
52
            const INPUT: &str = "1234567890";
53
            let buf = [0_i8; INPUT.len() + 1];
54
            assert!(copy_to_c_char(
55
                INPUT.to_string(),
56
                buf.as_ptr() as *mut c_char,
57
                buf.len()
58
            ));
59
            // Note that while CStr::from_ptr is documented to take a
60
            // *const i8, on Arm/Arm64 it actually takes a *const
61
            // u8. So cast it c_char which is an alias for the correct
62
            // type depending on the arch.
63
            let output = std::ffi::CStr::from_ptr(buf.as_ptr() as *const c_char)
64
                .to_str()
65
                .unwrap();
66
            assert_eq!(INPUT, output);
67
        };
68
    }
69
70
    // Test `copy_to_c_char` with too short of an output buffer to
71
    // make sure false is returned.
72
    #[test]
73
    fn test_copy_to_c_char_short_output() {
74
        unsafe {
75
            const INPUT: &str = "1234567890";
76
            let buf = [0_i8; INPUT.len()];
77
            assert!(!copy_to_c_char(
78
                INPUT.to_string(),
79
                buf.as_ptr() as *mut c_char,
80
                buf.len()
81
            ));
82
        };
83
    }
84
}