Skip to content

Commit 6d1a0ed

Browse files
fix(data): Allocate empty array on tw_data_create_with_bytes if data is NULL (trustwallet#4508)
* fix(data): Allocate empty array on `tw_data_create_with_bytes` if data is NULL * fix(data): Add TWData test
1 parent 7f6004b commit 6d1a0ed

File tree

8 files changed

+44
-25
lines changed

8 files changed

+44
-25
lines changed

rust/tw_keypair/src/ffi/asn.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ pub unsafe extern "C" fn ecdsa_signature_from_asn_der(
3232
encoded_len: usize,
3333
) -> CByteArrayResult {
3434
let encoded_ref = CByteArrayRef::new(encoded, encoded_len);
35-
let Some(encoded) = encoded_ref.to_vec() else {
36-
return CByteArrayResult::error(CKeyPairError::InvalidSignature);
37-
};
35+
let encoded = encoded_ref.to_vec();
3836

3937
der::Signature::from_bytes(encoded.as_slice())
4038
.map(|sign| CByteArray::from(sign.to_vec()))

rust/tw_keypair/src/ffi/privkey.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub unsafe extern "C" fn tw_private_key_create_with_data(
3333
input_len: usize,
3434
) -> *mut TWPrivateKey {
3535
let bytes_ref = CByteArrayRef::new(input, input_len);
36-
let bytes = try_or_else!(bytes_ref.to_vec(), std::ptr::null_mut);
36+
let bytes = bytes_ref.to_vec();
3737

3838
PrivateKey::new(bytes)
3939
.map(|private| TWPrivateKey(private).into_ptr())
@@ -85,7 +85,7 @@ pub unsafe extern "C" fn tw_private_key_is_valid(
8585
curve: u32,
8686
) -> bool {
8787
let curve = try_or_false!(Curve::from_raw(curve));
88-
let priv_key_slice = try_or_false!(CByteArrayRef::new(key, key_len).as_slice());
88+
let priv_key_slice = CByteArrayRef::new(key, key_len).as_slice();
8989
PrivateKey::is_valid(priv_key_slice, curve)
9090
}
9191

@@ -105,10 +105,7 @@ pub unsafe extern "C" fn tw_private_key_sign(
105105
) -> CByteArray {
106106
let curve = try_or_else!(Curve::from_raw(curve), CByteArray::default);
107107
let private = try_or_else!(TWPrivateKey::from_ptr_as_ref(key), CByteArray::default);
108-
let message_to_sign = try_or_else!(
109-
CByteArrayRef::new(message, message_len).as_slice(),
110-
CByteArray::default
111-
);
108+
let message_to_sign = CByteArrayRef::new(message, message_len).as_slice();
112109

113110
// Return an empty signature if an error occurs.
114111
let sig = private.0.sign(message_to_sign, curve).unwrap_or_default();

rust/tw_keypair/src/ffi/pubkey.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub unsafe extern "C" fn tw_public_key_create_with_data(
3434
ty: u32,
3535
) -> *mut TWPublicKey {
3636
let bytes_ref = CByteArrayRef::new(input, input_len);
37-
let bytes = try_or_else!(bytes_ref.to_vec(), std::ptr::null_mut);
37+
let bytes = bytes_ref.to_vec();
3838
let ty = try_or_else!(PublicKeyType::from_raw(ty), std::ptr::null_mut);
3939
PublicKey::new(bytes, ty)
4040
.map(|public| TWPublicKey(public).into_ptr())
@@ -67,8 +67,8 @@ pub unsafe extern "C" fn tw_public_key_verify(
6767
msg_len: usize,
6868
) -> bool {
6969
let public = try_or_false!(TWPublicKey::from_ptr_as_ref(key));
70-
let sig = try_or_false!(CByteArrayRef::new(sig, sig_len).as_slice());
71-
let msg = try_or_false!(CByteArrayRef::new(msg, msg_len).as_slice());
70+
let sig = CByteArrayRef::new(sig, sig_len).as_slice();
71+
let msg = CByteArrayRef::new(msg, msg_len).as_slice();
7272
public.0.verify(sig, msg)
7373
}
7474

rust/tw_memory/src/ffi/c_byte_array_ref.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ impl CByteArrayRef {
2222
/// # Safety
2323
///
2424
/// The inner data must be valid.
25-
pub unsafe fn to_vec(&self) -> Option<Vec<u8>> {
26-
self.as_slice().map(|data| data.to_vec())
25+
pub unsafe fn to_vec(&self) -> Vec<u8> {
26+
self.as_slice().to_vec()
2727
}
2828

2929
/// Returns a slice.
@@ -32,10 +32,10 @@ impl CByteArrayRef {
3232
/// # Safety
3333
///
3434
/// The inner data must be valid.
35-
pub unsafe fn as_slice(&self) -> Option<&'static [u8]> {
35+
pub unsafe fn as_slice(&self) -> &'static [u8] {
3636
if self.data.is_null() {
37-
return None;
37+
return &[];
3838
}
39-
Some(std::slice::from_raw_parts(self.data, self.size))
39+
std::slice::from_raw_parts(self.data, self.size)
4040
}
4141
}

rust/tw_memory/src/ffi/tw_data.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ impl TWData {
2020
}
2121

2222
/// Creates a `TWData` from a raw byte array.
23-
pub unsafe fn from_raw_data(bytes: *const u8, size: usize) -> Option<TWData> {
24-
CByteArrayRef::new(bytes, size).to_vec().map(TWData)
23+
pub unsafe fn from_raw_data(bytes: *const u8, size: usize) -> TWData {
24+
TWData(CByteArrayRef::new(bytes, size).to_vec())
2525
}
2626

2727
/// Converts `TWData` into `Data` without additional allocation.
@@ -65,9 +65,7 @@ impl RawPtrTrait for TWData {}
6565
/// \return Non-null filled block of data.
6666
#[no_mangle]
6767
pub unsafe extern "C" fn tw_data_create_with_bytes(bytes: *const u8, size: usize) -> *mut TWData {
68-
TWData::from_raw_data(bytes, size)
69-
.map(|data| data.into_ptr())
70-
.unwrap_or_else(std::ptr::null_mut)
68+
TWData::from_raw_data(bytes, size).into_ptr()
7169
}
7270

7371
/// Deletes a block of data created with a `TWDataCreate*` method.

rust/tw_memory/src/ffi/tw_string.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ pub struct TWString(CString);
1616

1717
impl TWString {
1818
pub unsafe fn is_utf8_string(bytes: *const u8, size: usize) -> bool {
19-
let Some(bytes) = CByteArrayRef::new(bytes, size).to_vec() else {
20-
return false;
21-
};
19+
let bytes = CByteArrayRef::new(bytes, size).to_vec();
2220
String::from_utf8(bytes).is_ok()
2321
}
2422

tests/chains/Ethereum/BarzTests.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,24 @@ TEST(Barz, SignAuthorization) {
423423
}
424424
}
425425

426+
TEST(Barz, SignAuthorizationZeroNonce) {
427+
{
428+
const auto chainId = store(uint256_t(1));
429+
const auto contractAddress = "0xB91aaa96B138A1B1D94c9df4628187132c5F2bf1";
430+
const Data nonce;
431+
const auto privateKey = "0x947dd69af402e7f48da1b845dfc1df6be593d01a0d8274bd03ec56712e7164e8";
432+
433+
const auto signedAuthorization = WRAPS(TWBarzSignAuthorization(WRAPD(TWDataCreateWithBytes(chainId.data(), chainId.size())).get(), STRING(contractAddress).get(), WRAPD(TWDataCreateWithBytes(nonce.data(), nonce.size())).get(), STRING(privateKey).get()));
434+
auto json = nlohmann::json::parse(std::string(TWStringUTF8Bytes(signedAuthorization.get())));
435+
ASSERT_EQ(json["chainId"], hexEncoded(chainId));
436+
ASSERT_EQ(json["address"], contractAddress);
437+
ASSERT_EQ(json["nonce"], "0x00");
438+
ASSERT_EQ(json["yParity"], hexEncoded(store(uint256_t(0))));
439+
ASSERT_EQ(json["r"], "0x2269a34ea41b8898fb28196c3548836e2df0efe5968574be1cefc0355af11c24");
440+
ASSERT_EQ(json["s"], "0x601b4443deafb48303d4f4a580505485e3fa7f516472675227494a88e9d0a5b5");
441+
}
442+
}
443+
426444
TEST(Barz, GetEncodedHash) {
427445
{
428446
const auto chainId = store(uint256_t(31337), 32);

tests/common/DataTests.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,13 @@ TEST(DataTests, hasPrefix) {
9292
const Data prefix23 = parse_hex("bb");
9393
EXPECT_FALSE(has_prefix(data, prefix23));
9494
}
95+
96+
TEST(DataTests, rustEmptyArray) {
97+
Data empty;
98+
EXPECT_EQ(empty.size(), 0ul);
99+
EXPECT_EQ(empty.data(), nullptr);
100+
auto* rustPtr = Rust::tw_data_create_with_bytes(empty.data(), empty.size());
101+
EXPECT_NE(rustPtr, nullptr);
102+
EXPECT_EQ(Rust::tw_data_size(rustPtr), 0);
103+
Rust::tw_data_delete(rustPtr);
104+
}

0 commit comments

Comments
 (0)