簡體   English   中英

可以通過 C++ 訪問堆棧分配的 Rust 緩沖區嗎?

[英]Can a stack allocated Rust buffer be accessed through C++?

為了避免頭部分配,並且因為我知道以太網數據包的最大 MTU,我在 Rust 中創建了一個小buffer: [u8, MAX_BYTES_TRANSPORT] ,C++ 應該為我填充:

pub fn receive(&mut self, f: &dyn Fn(&[u8])) -> std::result::Result<(), &str> {
    let mut buffer: [u8; MAX_BYTES_TRANSPORT] = [0; MAX_BYTES_TRANSPORT];
    //number of bytes written in buffer in the C++ side
    let written_size: *mut size_t = std::ptr::null_mut::<size_t>();
    let r = unsafe{openvpn_client_receive_just(
        buffer.as_mut_ptr(), buffer.len(), written_size, self.openvpn_client)};

So, the function openvpn_client_receive_just , which is a C++ function with C interface, should write to this buffer. 這安全嗎? 我找不到有關在 C++ 中使用的堆棧分配 Rust 緩沖區的信息

這是 function:

uint8_t openvpn_client_receive_just(
    uint8_t *buffer, size_t buffer_size, size_t *written_size, OpenVPNSocket *client)

可以通過 C++ 訪問堆棧分配的緩沖區嗎?

的。

從類型系統的角度來看,靜態分配、堆棧分配或堆分配之間沒有區別:C 簽名只接受指針和大小,而很少關心指針指向的位置。

這安全嗎?

最有可能

只要正確寫入 C function 並遵守緩沖區的邊界,這將是安全的。 如果沒有,那是一個錯誤。

有人可能會爭辯說,最好有一個堆分配的緩沖區,但老實說,一旦開始寫入越界,覆蓋任意堆棧字節或覆蓋任意堆字節都是不好的,並且具有未定義的行為。

為了額外的安全性,您可以使用嵌套在 2 個保護頁面之間的堆分配。 使用特定於操作系統的工具,您可以分配 3 個連續的操作系統頁面(在 x86 上通常每個 4KB),然后將第一個和最后一個標記為只讀並將緩沖區放在中間。 然后,操作系統將捕獲緩沖區之前或之后的任何(關閉)寫入。 但是,更大的跳躍不會……所以要減輕負擔就需要付出很多努力。

你的代碼安全嗎?

您很可能需要知道寫入了多少字節,因此使用 null 指針很奇怪。

我希望看到:

let mut written: size_t = 0;
let written_size = &mut written as *mut _;

是的,這又是一個指向堆棧變量的指針,就像在 C 中一樣。


關於風格的說明。 您的 Rust 代碼不尋常,因為您使用完全類型化的變量和完整路徑,更慣用的樣式是:

// Result is implicitly in scope.

pub fn receive(&mut self, f: &dyn Fn(&[u8])) -> Result<(), &str) {
    let mut buffer = [0u8; MAX_BYTES_TRANSPORT];

    let mut written: size_t = 0;
    let written_size = &mut written as *mut _;

    //  Safety:
    //  <enumerate preconditions to safely call the function here, and why they are met>
    let result = unsafe {
        openvpn_client_receive_just(
            buffer.as_mut_ptr(), buffer.len(), written_size, self.openvpn_client)
    };

    translate_openvpn_error(result)?;

    let buffer = &buffer[0..written];
    f(buffer);

    Ok(())
}

我確實注釋了類型, written幫助推理,但嚴格來說它不應該是必要的。

此外,我喜歡在我所做的每一個不安全的調用前加上使其安全的先決條件列表,以及滿足它們的每個原因。 它可以幫助我稍后審核我的不安全代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM