Track lengths when copying receiver data from C++ to Rust

Co-authored-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
str4d 2021-07-30 01:34:57 +01:00 committed by Jack Grigg
parent 635151bf75
commit 037bfa32f3
3 changed files with 12 additions and 10 deletions

View File

@ -70,13 +70,15 @@ static size_t GetReceiverLen(const void* ua, size_t index)
class CopyDataForReceiver {
unsigned char* data;
size_t length;
public:
CopyDataForReceiver(unsigned char* data) : data(data) {}
CopyDataForReceiver(unsigned char* data, size_t length) : data(data), length(length) {}
void operator()(const libzcash::SaplingPaymentAddress &zaddr) const {
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << zaddr;
assert(length == ss.size());
memcpy(data, ss.data(), ss.size());
}
@ -96,10 +98,10 @@ public:
/**
* `data` MUST be the correct length for the receiver at this index.
*/
static void GetReceiver(const void* ua, size_t index, unsigned char* data)
static void GetReceiver(const void* ua, size_t index, unsigned char* data, size_t length)
{
std::visit(
CopyDataForReceiver(data),
CopyDataForReceiver(data, length),
reinterpret_cast<const libzcash::UnifiedAddress*>(ua)->GetReceiversAsParsed()[index]);
}

View File

@ -17,7 +17,7 @@ typedef bool (*unknown_receiver_t)(
size_t len);
typedef uint8_t (*get_typecode_t)(const void* ua, size_t index);
typedef size_t (*get_receiver_len_t)(const void* ua, size_t index);
typedef void (*get_receiver_t)(const void* ua, size_t index, unsigned char* data);
typedef void (*get_receiver_t)(const void* ua, size_t index, unsigned char* data, size_t length);
/// Parses a unified address from the given string.
bool zcash_address_parse_unified(

View File

@ -21,7 +21,7 @@ pub type GetTypecodeCb = unsafe extern "C" fn(ua: Option<UnifiedAddressObj>, ind
pub type GetReceiverLenCb =
unsafe extern "C" fn(ua: Option<UnifiedAddressObj>, index: usize) -> usize;
pub type GetReceiverDataCb =
unsafe extern "C" fn(ua: Option<UnifiedAddressObj>, index: usize, data: *mut u8);
unsafe extern "C" fn(ua: Option<UnifiedAddressObj>, index: usize, data: *mut u8, length: usize);
fn network_from_cstr(network: *const c_char) -> Option<Network> {
match unsafe { CStr::from_ptr(network) }.to_str().unwrap() {
@ -169,7 +169,7 @@ pub extern "C" fn zcash_address_serialize_unified(
// TODO: Replace with Orchard support.
let data_len = unsafe { (receiver_len_cb.unwrap())(ua_obj, i) };
let mut data = vec![0; data_len];
unsafe { (receiver_cb.unwrap())(ua_obj, i, data.as_mut_ptr()) };
unsafe { (receiver_cb.unwrap())(ua_obj, i, data.as_mut_ptr(), data_len) };
unified::Receiver::Unknown {
typecode: 0x03,
data,
@ -177,23 +177,23 @@ pub extern "C" fn zcash_address_serialize_unified(
}
unified::Typecode::Sapling => {
let mut data = [0; 43];
unsafe { (receiver_cb.unwrap())(ua_obj, i, data.as_mut_ptr()) };
unsafe { (receiver_cb.unwrap())(ua_obj, i, data.as_mut_ptr(), data.len()) };
unified::Receiver::Sapling(data)
}
unified::Typecode::P2sh => {
let mut data = [0; 20];
unsafe { (receiver_cb.unwrap())(ua_obj, i, data.as_mut_ptr()) };
unsafe { (receiver_cb.unwrap())(ua_obj, i, data.as_mut_ptr(), data.len()) };
unified::Receiver::P2sh(data)
}
unified::Typecode::P2pkh => {
let mut data = [0; 20];
unsafe { (receiver_cb.unwrap())(ua_obj, i, data.as_mut_ptr()) };
unsafe { (receiver_cb.unwrap())(ua_obj, i, data.as_mut_ptr(), data.len()) };
unified::Receiver::P2pkh(data)
}
unified::Typecode::Unknown(typecode) => {
let data_len = unsafe { (receiver_len_cb.unwrap())(ua_obj, i) };
let mut data = vec![0; data_len];
unsafe { (receiver_cb.unwrap())(ua_obj, i, data.as_mut_ptr()) };
unsafe { (receiver_cb.unwrap())(ua_obj, i, data.as_mut_ptr(), data_len) };
unified::Receiver::Unknown { typecode, data }
}
},