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 { class CopyDataForReceiver {
unsigned char* data; unsigned char* data;
size_t length;
public: 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 { void operator()(const libzcash::SaplingPaymentAddress &zaddr) const {
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << zaddr; ss << zaddr;
assert(length == ss.size());
memcpy(data, ss.data(), 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. * `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( std::visit(
CopyDataForReceiver(data), CopyDataForReceiver(data, length),
reinterpret_cast<const libzcash::UnifiedAddress*>(ua)->GetReceiversAsParsed()[index]); reinterpret_cast<const libzcash::UnifiedAddress*>(ua)->GetReceiversAsParsed()[index]);
} }

View File

@ -17,7 +17,7 @@ typedef bool (*unknown_receiver_t)(
size_t len); size_t len);
typedef uint8_t (*get_typecode_t)(const void* ua, size_t index); 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 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. /// Parses a unified address from the given string.
bool zcash_address_parse_unified( 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 = pub type GetReceiverLenCb =
unsafe extern "C" fn(ua: Option<UnifiedAddressObj>, index: usize) -> usize; unsafe extern "C" fn(ua: Option<UnifiedAddressObj>, index: usize) -> usize;
pub type GetReceiverDataCb = 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> { fn network_from_cstr(network: *const c_char) -> Option<Network> {
match unsafe { CStr::from_ptr(network) }.to_str().unwrap() { 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. // TODO: Replace with Orchard support.
let data_len = unsafe { (receiver_len_cb.unwrap())(ua_obj, i) }; let data_len = unsafe { (receiver_len_cb.unwrap())(ua_obj, i) };
let mut data = vec![0; data_len]; 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 { unified::Receiver::Unknown {
typecode: 0x03, typecode: 0x03,
data, data,
@ -177,23 +177,23 @@ pub extern "C" fn zcash_address_serialize_unified(
} }
unified::Typecode::Sapling => { unified::Typecode::Sapling => {
let mut data = [0; 43]; 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::Receiver::Sapling(data)
} }
unified::Typecode::P2sh => { unified::Typecode::P2sh => {
let mut data = [0; 20]; 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::Receiver::P2sh(data)
} }
unified::Typecode::P2pkh => { unified::Typecode::P2pkh => {
let mut data = [0; 20]; 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::Receiver::P2pkh(data)
} }
unified::Typecode::Unknown(typecode) => { unified::Typecode::Unknown(typecode) => {
let data_len = unsafe { (receiver_len_cb.unwrap())(ua_obj, i) }; let data_len = unsafe { (receiver_len_cb.unwrap())(ua_obj, i) };
let mut data = vec![0; data_len]; 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 } unified::Receiver::Unknown { typecode, data }
} }
}, },