mirror of
https://github.com/chatmail/core.git
synced 2026-05-07 08:56:30 +03:00
fix(ffi): don't steal Arc in dc_jsonrpc_init (#7962)
dc_jsonrpc_init called Arc::from_raw on the account_manager pointer, which took ownership of the caller's refcount. When the local Arc dropped at the end of the function, the refcount was decremented, leaving the C side's pointer with a stolen refcount. This caused a use-after-free race between dc_accounts_unref and dc_jsonrpc_unref at shutdown. Wrap in ManuallyDrop to prevent the implicit drop, keeping the caller's refcount intact. Regression introduced in #7662.
This commit is contained in:
@@ -15,6 +15,7 @@ use std::collections::BTreeMap;
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, LazyLock, Mutex};
|
use std::sync::{Arc, LazyLock, Mutex};
|
||||||
@@ -5150,10 +5151,10 @@ pub unsafe extern "C" fn dc_jsonrpc_init(
|
|||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
let account_manager = Arc::from_raw(account_manager);
|
let account_manager = ManuallyDrop::new(Arc::from_raw(account_manager));
|
||||||
let cmd_api = block_on(deltachat_jsonrpc::api::CommandApi::from_arc(
|
let cmd_api = block_on(deltachat_jsonrpc::api::CommandApi::from_arc(Arc::clone(
|
||||||
account_manager.clone(),
|
&account_manager,
|
||||||
));
|
)));
|
||||||
|
|
||||||
let (request_handle, receiver) = RpcClient::new();
|
let (request_handle, receiver) = RpcClient::new();
|
||||||
let handle = RpcSession::new(request_handle, cmd_api);
|
let handle = RpcSession::new(request_handle, cmd_api);
|
||||||
|
|||||||
Reference in New Issue
Block a user