mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-04-14 10:07:39 +08:00
septentrio: add fuzz tests
This commit is contained in:
parent
d31f227f15
commit
e50f1774ae
@ -48,3 +48,15 @@ px4_add_module(
|
||||
MODULE_CONFIG
|
||||
module.yaml
|
||||
)
|
||||
|
||||
px4_add_functional_gtest(SRC septentrio_fuzz_tests.cpp
|
||||
LINKLIBS
|
||||
driver__septentrio
|
||||
COMPILE_FLAGS
|
||||
# There warnings come from within fuzztest
|
||||
-Wno-float-equal
|
||||
-Wno-sign-compare
|
||||
-Wno-shadow
|
||||
-Wno-extra
|
||||
-Wno-non-template-friend
|
||||
)
|
||||
|
||||
@ -262,8 +262,14 @@ bool Decoder::done() const
|
||||
|
||||
bool Decoder::can_parse() const
|
||||
{
|
||||
return done() && _message.header.length <= sizeof(_message) && _message.header.length > 4
|
||||
&& _message.header.crc == buffer_crc16(reinterpret_cast<const uint8_t *>(&_message) + 4, _message.header.length - 4);
|
||||
const bool precondition = done() && _message.header.length <= sizeof(_message) && _message.header.length > 4;
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
// When fuzzing, disable the CRC check as it is hard for the fuzzer to find msgs with valid CRC.
|
||||
return precondition;
|
||||
#else
|
||||
return precondition &&
|
||||
_message.header.crc == buffer_crc16(reinterpret_cast<const uint8_t *>(&_message) + 4, _message.header.length - 4);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace sbf
|
||||
|
||||
@ -206,6 +206,13 @@ public:
|
||||
* become ready for the next message.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* @brief Check whether a full message has been received and is valid.
|
||||
*
|
||||
* @return `true` if the data can be parsed, `false` if the message is incomplete or not valid.
|
||||
*/
|
||||
bool can_parse() const;
|
||||
private:
|
||||
/**
|
||||
* @brief Check whether a full message has been received.
|
||||
@ -216,13 +223,6 @@ private:
|
||||
*/
|
||||
bool done() const;
|
||||
|
||||
/**
|
||||
* @brief Check whether a full message has been received and is valid.
|
||||
*
|
||||
* @return `true` if the data can be parsed, `false` if the message is incomplete or not valid.
|
||||
*/
|
||||
bool can_parse() const;
|
||||
|
||||
State _state{State::SearchingSync1};
|
||||
uint16_t _current_index{0};
|
||||
message_t _message;
|
||||
|
||||
@ -282,6 +282,13 @@ public:
|
||||
* Default baud rate, used when the user requested an invalid baud rate.
|
||||
*/
|
||||
static uint32_t k_default_baud_rate;
|
||||
|
||||
/**
|
||||
* @brief Parse the next byte of a received message from the receiver.
|
||||
*
|
||||
* @return 0 = decoding, 1 = message handled, 2 = sat info message handled
|
||||
*/
|
||||
int parse_char(const uint8_t byte);
|
||||
private:
|
||||
enum class State {
|
||||
OpeningSerialPort,
|
||||
@ -407,13 +414,6 @@ private:
|
||||
*/
|
||||
ConfigureResult configure();
|
||||
|
||||
/**
|
||||
* @brief Parse the next byte of a received message from the receiver.
|
||||
*
|
||||
* @return 0 = decoding, 1 = message handled, 2 = sat info message handled
|
||||
*/
|
||||
int parse_char(const uint8_t byte);
|
||||
|
||||
/**
|
||||
* @brief Process a fully received message from the receiver.
|
||||
*
|
||||
|
||||
151
src/drivers/gnss/septentrio/septentrio_fuzz_tests.cpp
Normal file
151
src/drivers/gnss/septentrio/septentrio_fuzz_tests.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2025 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "septentrio.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <fuzztest/fuzztest.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
TEST(SeptentrioTestDecoding, decodeMessage)
|
||||
{
|
||||
// Check if a single message can be decoded
|
||||
septentrio::sbf::message_t m{};
|
||||
m.header.sync1 = '$';
|
||||
m.header.sync2 = '@';
|
||||
m.header.id_number = septentrio::sbf::BlockID::PVTGeodetic;
|
||||
m.header.length = sizeof(m.header) + sizeof(septentrio::sbf::PVTGeodetic);
|
||||
septentrio::sbf::PVTGeodetic pvt{};
|
||||
pvt.latitude = 123;
|
||||
pvt.longitude = 456;
|
||||
pvt.height = 789;
|
||||
memcpy(&m.payload, &pvt, sizeof(pvt));
|
||||
m.header.crc = septentrio::buffer_crc16((uint8_t *)&m + 4, m.header.length - 4);
|
||||
|
||||
septentrio::sbf::Decoder decoder;
|
||||
const uint8_t *buffer = (const uint8_t *)&m;
|
||||
|
||||
for (int i = 0; i < m.header.length; ++i) {
|
||||
decoder.add_byte(buffer[i]);
|
||||
}
|
||||
|
||||
ASSERT_EQ(decoder.id(), septentrio::sbf::BlockID::PVTGeodetic);
|
||||
|
||||
septentrio::sbf::Header header;
|
||||
ASSERT_EQ(decoder.parse(&header), 0);
|
||||
}
|
||||
|
||||
|
||||
class SeptentrioTestDecoder
|
||||
{
|
||||
public:
|
||||
SeptentrioTestDecoder()
|
||||
{
|
||||
// This object will be reused for each fuzzing iteration call
|
||||
}
|
||||
~SeptentrioTestDecoder() = default;
|
||||
|
||||
void runTest(const std::vector<uint8_t> &data)
|
||||
{
|
||||
++_num_runs;
|
||||
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
if (_decoder.add_byte(data[i]) == septentrio::sbf::Decoder::State::Done) {
|
||||
++_num_msgs;
|
||||
|
||||
if (_num_runs % 100'000 == 0) {
|
||||
printf("Message: %i / %i / %i (%.6f)\n", _num_headers, _num_msgs, _num_runs, (double)_num_headers / _num_runs);
|
||||
}
|
||||
|
||||
septentrio::sbf::Header message;
|
||||
|
||||
if (_decoder.parse(&message) == 0) {
|
||||
++_num_headers;
|
||||
}
|
||||
|
||||
_decoder.reset();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private:
|
||||
septentrio::sbf::Decoder _decoder;
|
||||
int _num_runs{0};
|
||||
int _num_msgs{0};
|
||||
int _num_headers{0};
|
||||
};
|
||||
|
||||
FUZZ_TEST_F(SeptentrioTestDecoder, runTest);
|
||||
|
||||
class SeptentrioTest
|
||||
{
|
||||
public:
|
||||
SeptentrioTest()
|
||||
: _driver("", septentrio::Instance::Main, 0)
|
||||
{
|
||||
// This object will be reused for each fuzzing iteration call
|
||||
}
|
||||
|
||||
~SeptentrioTest() = default;
|
||||
|
||||
void runTest(const std::vector<uint8_t> &data)
|
||||
{
|
||||
++_num_runs;
|
||||
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
if (_driver.parse_char(data[i]) > 0) {
|
||||
++_num_msgs;
|
||||
}
|
||||
}
|
||||
|
||||
if (_num_runs % 100'000 == 0) {
|
||||
// Print some stats (note that a high _num_msgs could also mean the fuzzer sends always the same message)
|
||||
printf("Parsed messages: %i / %i iterations (Rate: %.6f)\n", _num_msgs, _num_runs, (double)_num_msgs / _num_runs);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::tuple<std::vector<uint8_t>>> seeds() { return _seeds; }
|
||||
|
||||
private:
|
||||
septentrio::SeptentrioDriver _driver;
|
||||
|
||||
int _num_runs{0};
|
||||
int _num_msgs{0};
|
||||
|
||||
// Provide a valid PVTGeodetic message as seed
|
||||
const std::vector<std::tuple<std::vector<uint8_t>>> _seeds = {{{0x24, 0x40, 0xe8, 0x88, 0xa7, 0x0f, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}};
|
||||
};
|
||||
|
||||
FUZZ_TEST_F(SeptentrioTest, runTest).WithSeeds(&SeptentrioTest::seeds);
|
||||
Loading…
x
Reference in New Issue
Block a user