NFTBridge
60,000 USDC
View results
Submission Details
Severity: low
Invalid

Incorrect Implementation of the `try_into` Trait for the `felt252` Data Type Leads to Issues in Data Serialization.

Summary

The process of converting the felt252 data type into a ByteArray is not implemented correctly. This flaw creates a vulnerability that affects how data is serialized across the protocol, potentially causing significant issues with data integrity.

Vulnerability Details

The ByteArray type, as outlined in the StarkNet documentation, is composed of three main fields:

  • data

  • pending_word

  • pending_word_len

When serializing, the pending_word field should not exceed a size of 30 bytes.

However, let's examine the current implementation of the try_into trait for the felt252 type:

impl FeltTryIntoByteArray of TryInto<felt252, ByteArray> {
fn try_into(self: felt252) -> Option<ByteArray> {
let mut res: ByteArray = Default::default();
res.pending_word = self;
let mut length = 0;
let mut data: u256 = self.into();
loop {
if data == 0 {
break;
}
data /= 0x100;
length += 1;
};
res.pending_word_len = length;
Option::Some(res)
}
}

In this code, the logic does not verify whether the value fits within the 31-byte limit before assigning it to the pending_word field. Instead, the code simply stores the data in pending_word without adequate validation.

This oversight can lead to serious problems during serialization, especially when the value exceeds 30 bytes. In such cases, the serialization process could produce incorrect results, leading to misinterpretation of the data or failure in certain situations.

Impact

The improper serialization of the felt252 type can result in incorrect data being processed, which may cause data to be misinterpreted or cause the process to fail altogether. This vulnerability could have significant consequences, especially in scenarios where accurate data serialization is critical.

Tools Used

Manual Review

Recommendations

To resolve this issue, the implementation should first check if the self value exceeds 30 bytes. If it does, the data should be stored in the data field instead of pending_word. If the value is within the 30-byte limit, the existing logic can be used as is.

Updates

Lead Judging Commences

n0kto Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid-31bytes-felt252-try_into-BytesArray-incorrect-decoding

Great catch ! Unfortunatelly there is no impact... :/ I simulated the end of the calling functions and it seems that the "span" conversion handle that case. Here is my PoC: ``` fn input_31_byte() { let a: felt252 = 'qwertyuiopasdfghjklzxcvbnm12345'; let mut out_uris = array![]; let convert: Option<ByteArray> = a.try_into(); match convert { Option::Some(e) => { out_uris.append(e); }, Option::None => panic!("Should not be None") } let span = out_uris.span(); println!("Real data used in the calling function {:?}", span[0]); let b: ByteArray = "qwertyuiopasdfghjklzxcvbnm12345"; let mut out_uris_2 = array![]; out_uris_2.append(b); println!("Real data used in the calling function {:?}", out_uris_2.span()[0]); } ```

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.