SBF driver
devbharat opened this issue · 3 comments
Line 393 in ddb1825
If the length bytes are corrupt(_buf.Len is meaningless), the length arg to the crc16 call could overrun and cause hardfault. You can check it for %4 == 0 for sanity, and use _rxReadBytes instead of _buf.len to ensure you don’t go beyond sizeof(_buf)
fyi @skimslozo
@devbharat I don't quite understand it. When or how is _buf.length
corrupt, or wrong? And how could that be caught?
From the SBF reference manual
The length bytes are the 7th and 8th bytes of the header. It’s similar to how the old sdlog2 used to work, you start parsing at the two sync bytes „$@„ then get 2 crc bytes, two packet type bytes followed by two length bytes and then the rest of the payload. All this goes into a fixed size buffer _buf (union) (allocated in the header if I remember) one by one from the serial stream. While copying the bytes from the stream, we are careful to not exceed the allocated size even if _buf.length tells us to (on this line) as one of the two or both bytes could be corrupted in transmission, but you can only know for sure after verifying the CRC. So until now it’s all good. The problem is, to tell CRC how many bytes to run through, we don’t use the variable representing how many bytes we read, which is ‚safe‘ against the size of _buf, but directly use the ‚interpreted value‘ of _buf.length formed out of the 7th and 8th bytes of the transmitted packet (starting from the stream). Imagine if they were FF FF.
A change like this below is safer
if (_buf.length <= 4
|| _buf.crc16 != crc16(reinterpret_cast<uint8_t *>(&_buf) + 4,
(_rx_payload_index > sizeof(_buf) ? sizeof(_buf) : _rx_payload_index) - 4)) {
failure_cntr.crc_fail++;
PX4_DEBUG("[SBF PARSER] crc_fail_cnt: %d", failure_cntr.crc_fail);
return 1;
}
@devbharat I gave this a try in #107, slightly different from your suggestion. I think it's simple enough and correct...