Compare commits

...

11 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] fe7bf8472b Add static_assert to verify LOG_FILEPATH_SCANF_WIDTH is synchronized
- Add compile-time check that LOG_FILEPATH_SIZE == 256
- Ensures LOG_FILEPATH_SCANF_WIDTH stays synchronized if buffer size changes
- Provides clear error message if someone modifies LOG_FILEPATH_SIZE

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:50:04 +00:00
copilot-swe-agent[bot] ca336fb299 Use LOG_FILEPATH_SCANF_WIDTH macro for format specifier
- Define LOG_FILEPATH_SCANF_WIDTH macro for the sscanf width specifier
- Replace hardcoded '255' with the named macro in both sscanf calls
- Improves maintainability and makes the relationship between buffer size and width explicit
- Addresses final code review feedback about magic numbers

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:49:01 +00:00
copilot-swe-agent[bot] 5cdc783b05 Remove duplicate constant and use header LOG_FILEPATH_SIZE
- Remove duplicate LOG_FILEPATH_SIZE macro from cpp file
- Use MavlinkLogHandler::LOG_FILEPATH_SIZE consistently throughout
- Update local filepath buffer to use the same size as LogEntry.filepath
- Addresses code review feedback about duplication and consistency

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:47:25 +00:00
copilot-swe-agent[bot] 5037a96376 Define LOG_FILEPATH_SIZE constant for maintainability
- Add LOG_FILEPATH_SIZE constant (256) in both header and cpp
- Update LogEntry.filepath to use the constant
- Improve comments explaining width specifier relationship
- Addresses code review feedback about magic numbers

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:45:09 +00:00
copilot-swe-agent[bot] 8e0cabaeb7 Add static_assert and use consistent %255s width specifier
- Add static_assert to ensure PX4_MAX_FILEPATH >= 256 at compile time
- Use %255s consistently for both sscanf calls to prevent overflow
- Add explanatory comments for the width specifier choice
- Addresses code review feedback about potential overflow on NuttX

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:43:00 +00:00
copilot-swe-agent[bot] 338595edd1 Fix stack buffer overflow in mavlink_log_handler sscanf calls
- Increase LogEntry.filepath buffer from 60 to 256 bytes
- Add width specifiers to sscanf calls (%255s and %1023s) to prevent buffer overflow
- Prevents remote DoS vulnerability when parsing logdata.txt with excessively long filenames

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:37:29 +00:00
copilot-swe-agent[bot] f219c9f3b9 Initial plan 2025-12-15 21:33:02 +00:00
Brandon W. Banks 1345b3500a Vehicle command for Prearm Safety button (#26079)
* added vehicle command and support to remotely activate/deactivate the safety system (#26078)

* added print_status support for prearm safety status

* updated safety button to map to MAV_CMD_DO_SET_SAFETY_SWITCH_STATE = '5300'

* safety switch cmd: fixed incorrect catch-all and added commanded_state variable for easier reading
2025-12-15 11:25:32 -09:00
Balduin 8604604a5b logged_topics: clean up old commented-out topics (#26120) 2025-12-15 09:53:24 -09:00
bresch d62f112017 ekf2: prevent false mag fault detection
A false positive could be triggered if velocity fusion started,
then stopped after takeoff and only position fusion started again
(because velocity fusion timed out and had a timestamp > time_last_on_ground).
We now also check if the fusion timeout is due to the innovation being
rejected (and not just a temporary check failure or data interruption).
2025-12-15 14:06:04 +01:00
Farhang 14186cf74f [Tests] [CI] fix flaky altitude SITL test (#26106)
* test: increase altitude tolerance to fix flaky test

Altitude tolerance increased from 0.1f to 0.15f to handle simulation
timing variations. Test was failing at 0.201m with 0.2m tolerance.

* test: increase altitude tolerance further to 0.3m

* ci: re-add branch trigger for SITL tests

* Revert "ci: re-add branch trigger for SITL tests"

This reverts commit e5e4c9637b.
2025-12-13 09:13:23 -09:00
9 changed files with 91 additions and 12 deletions
+5
View File
@@ -100,6 +100,7 @@ uint16 VEHICLE_CMD_LOGGING_START = 2510 # Start streaming ULog data.
uint16 VEHICLE_CMD_LOGGING_STOP = 2511 # Stop streaming ULog data.
uint16 VEHICLE_CMD_CONTROL_HIGH_LATENCY = 2600 # Control starting/stopping transmitting data over the high latency link.
uint16 VEHICLE_CMD_DO_VTOL_TRANSITION = 3000 # Command VTOL transition.
uint16 VEHICLE_CMD_DO_SET_SAFETY_SWITCH_STATE = 5300 # Command safety on/off. |1 to activate safety, 0 to deactivate safety and allow control surface movements|Unused|Unused|Unused|Unused|Unused|Unused|
uint16 VEHICLE_CMD_ARM_AUTHORIZATION_REQUEST = 3001 # Request arm authorization.
uint16 VEHICLE_CMD_PAYLOAD_PREPARE_DEPLOY = 30001 # Prepare a payload deployment in the flight plan.
uint16 VEHICLE_CMD_PAYLOAD_CONTROL_DEPLOY = 30002 # Control a pre-programmed payload deployment.
@@ -179,6 +180,10 @@ int8 ARMING_ACTION_ARM = 1
uint8 GRIPPER_ACTION_RELEASE = 0
uint8 GRIPPER_ACTION_GRAB = 1
# Used as param1 in DO_SET_SAFETY_SWITCH_STATE command.
uint8 SAFETY_OFF = 0
uint8 SAFETY_ON = 1
uint8 ORB_QUEUE_LENGTH = 8
float32 param1 # Parameter 1, as defined by MAVLink uint16 VEHICLE_CMD enum.
+46
View File
@@ -302,6 +302,26 @@ int Commander::custom_command(int argc, char *argv[])
return 0;
}
if (!strcmp(argv[0], "safety")) {
if (argc < 2) {
PX4_ERR("missing argument");
return 1;
}
if (!strcmp(argv[1], "on")) {
send_vehicle_command(vehicle_command_s::VEHICLE_CMD_DO_SET_SAFETY_SWITCH_STATE, vehicle_command_s::SAFETY_ON);
} else if (!strcmp(argv[1], "off")) {
send_vehicle_command(vehicle_command_s::VEHICLE_CMD_DO_SET_SAFETY_SWITCH_STATE, vehicle_command_s::SAFETY_OFF);
} else {
PX4_ERR("invlaid argument, use [on|off]");
return 1;
}
return 0;
}
if (!strcmp(argv[0], "arm")) {
float param2 = 0.f;
@@ -495,6 +515,7 @@ int Commander::custom_command(int argc, char *argv[])
int Commander::print_status()
{
PX4_INFO("%s", isArmed() ? "Armed" : "Disarmed");
PX4_INFO("prearm safety: %s", _safety.isSafetyOff() ? "Off" : "On");
PX4_INFO("navigation mode: %s", mode_util::nav_state_names[_vehicle_status.nav_state]);
PX4_INFO("user intended navigation mode: %s", mode_util::nav_state_names[_vehicle_status.nav_state_user_intention]);
PX4_INFO("in failsafe: %s", _failsafe.inFailsafe() ? "yes" : "no");
@@ -1508,6 +1529,29 @@ Commander::handle_command(const vehicle_command_s &cmd)
answer_command(cmd, vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED);
break;
case vehicle_command_s::VEHICLE_CMD_DO_SET_SAFETY_SWITCH_STATE: {
// reject if armed, only allow pre or post flight for safety
if (isArmed()) {
answer_command(cmd, vehicle_command_ack_s::VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED);
} else {
int commanded_state = (int)cmd.param1;
if (commanded_state == vehicle_command_s::SAFETY_OFF) {
_safety.deactivateSafety();
answer_command(cmd, vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED);
} else if (commanded_state == vehicle_command_s::SAFETY_ON) {
_safety.activateSafety();
answer_command(cmd, vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED);
} else {
answer_command(cmd, vehicle_command_ack_s::VEHICLE_CMD_RESULT_FAILED);
}
}
}
break;
case vehicle_command_s::VEHICLE_CMD_START_RX_PAIR:
case vehicle_command_s::VEHICLE_CMD_CUSTOM_0:
case vehicle_command_s::VEHICLE_CMD_CUSTOM_1:
@@ -3026,6 +3070,8 @@ The commander module contains the state machine for mode switching and failsafe
PRINT_MODULE_USAGE_ARG("mag|baro|accel|gyro|level|esc|airspeed", "Calibration type", false);
PRINT_MODULE_USAGE_ARG("quick", "Quick calibration [mag, accel (not recommended)]", false);
PRINT_MODULE_USAGE_COMMAND_DESCR("check", "Run preflight checks");
PRINT_MODULE_USAGE_COMMAND_DESCR("safety", "Change prearm safety state");
PRINT_MODULE_USAGE_ARG("on|off", "[on] to activate safety, [off] to deactivate safety and allow control surface movements", false);
PRINT_MODULE_USAGE_COMMAND("arm");
PRINT_MODULE_USAGE_PARAM_FLAG('f', "Force arming (do not run preflight checks)", true);
PRINT_MODULE_USAGE_COMMAND("disarm");
+7
View File
@@ -76,3 +76,10 @@ void Safety::activateSafety()
_safety_off = false;
}
}
void Safety::deactivateSafety()
{
if (!_safety_disabled) {
_safety_off = true;
}
}
+1
View File
@@ -49,6 +49,7 @@ public:
bool safetyButtonHandler();
void activateSafety();
void deactivateSafety();
bool isButtonAvailable() const { return _button_available; }
bool isSafetyOff() const { return _safety_off; }
bool isSafetyDisabled() const { return _safety_disabled; }
@@ -104,12 +104,17 @@ void Ekf::controlGpsFusion(const imuSample &imu_delayed)
bool do_vel_pos_reset = false;
if (!_control_status.flags.gnss_fault && (_control_status.flags.gnss_vel || _control_status.flags.gnss_pos)) {
if (!_control_status.flags.gnss_fault && _control_status.flags.in_air && isYawFailure()) {
const bool velocity_fusion_failure = _aid_src_gnss_vel.innovation_rejected
&& isTimedOut(_time_last_hor_vel_fuse, _params.EKFGSF_reset_delay)
&& (_time_last_hor_vel_fuse > _time_last_on_ground_us);
if (_control_status.flags.in_air
&& isYawFailure()
&& isTimedOut(_time_last_hor_vel_fuse, _params.EKFGSF_reset_delay)
&& (_time_last_hor_vel_fuse > _time_last_on_ground_us)) {
const bool position_fusion_failure = _aid_src_gnss_pos.innovation_rejected
&& isTimedOut(_time_last_hor_pos_fuse, _params.EKFGSF_reset_delay)
&& (_time_last_hor_pos_fuse > _time_last_on_ground_us);
if ((_control_status.flags.gnss_vel && velocity_fusion_failure)
|| (_control_status.flags.gnss_pos && position_fusion_failure)) {
do_vel_pos_reset = tryYawEmergencyReset();
}
}
-2
View File
@@ -63,7 +63,6 @@ void LoggedTopics::add_default_topics()
add_optional_topic("external_ins_attitude");
add_optional_topic("external_ins_global_position");
add_optional_topic("external_ins_local_position");
// add_optional_topic("esc_status", 250);
add_topic("esc_status");
add_topic("failure_detector_status", 100);
add_topic("failsafe_flags");
@@ -209,7 +208,6 @@ void LoggedTopics::add_default_topics()
add_optional_topic_multi("vehicle_magnetometer", 500, 4);
add_topic("vehicle_optical_flow", 500);
add_topic("aux_global_position", 500);
//add_optional_topic("vehicle_optical_flow_vel", 100);
add_optional_topic("pps_capture");
// additional control allocation logging
+18 -3
View File
@@ -54,6 +54,17 @@ static const char *kLogDir = PX4_STORAGEDIR "/log";
#define PX4_MAX_FILEPATH PATH_MAX
#endif
// Ensure PX4_MAX_FILEPATH is large enough for our buffer sizes
// LogEntry.filepath uses MavlinkLogHandler::LOG_FILEPATH_SIZE
static_assert(PX4_MAX_FILEPATH >= MavlinkLogHandler::LOG_FILEPATH_SIZE,
"PX4_MAX_FILEPATH must be at least LOG_FILEPATH_SIZE bytes for log file paths");
// Width specifier for sscanf - must be LOG_FILEPATH_SIZE - 1
// This is hardcoded as 255 because preprocessor can't evaluate (256-1) in format strings
// The static_assert below ensures this stays synchronized with LOG_FILEPATH_SIZE
#define LOG_FILEPATH_SCANF_WIDTH "255"
static_assert(MavlinkLogHandler::LOG_FILEPATH_SIZE == 256, "Update LOG_FILEPATH_SCANF_WIDTH if LOG_FILEPATH_SIZE changes");
MavlinkLogHandler::MavlinkLogHandler(Mavlink &mavlink)
: _mavlink(mavlink)
{}
@@ -171,10 +182,12 @@ void MavlinkLogHandler::state_listing()
// We can send!
uint32_t size_bytes = 0;
uint32_t time_utc = 0;
char filepath[PX4_MAX_FILEPATH];
char filepath[MavlinkLogHandler::LOG_FILEPATH_SIZE];
// If parsed lined successfully, send the entry
if (sscanf(line, "%" PRIu32 " %" PRIu32 " %s", &time_utc, &size_bytes, filepath) != 3) {
// Note: Using width specifier to prevent buffer overflow
// Width is LOG_FILEPATH_SIZE-1 to leave room for null terminator
if (sscanf(line, "%" PRIu32 " %" PRIu32 " %" LOG_FILEPATH_SCANF_WIDTH "s", &time_utc, &size_bytes, filepath) != 3) {
PX4_DEBUG("sscanf failed");
continue;
}
@@ -506,7 +519,9 @@ bool MavlinkLogHandler::log_entry_from_id(uint16_t log_id, LogEntry *entry)
continue;
}
if (sscanf(line, "%" PRIu32 " %" PRIu32 " %s", &(entry->time_utc), &(entry->size_bytes), entry->filepath) != 3) {
// Parse log entry with width specifier to prevent buffer overflow
// Width is LOG_FILEPATH_SIZE-1 to leave room for null terminator
if (sscanf(line, "%" PRIu32 " %" PRIu32 " %" LOG_FILEPATH_SCANF_WIDTH "s", &(entry->time_utc), &(entry->size_bytes), entry->filepath) != 3) {
PX4_DEBUG("sscanf failed");
continue;
}
+3 -1
View File
@@ -48,12 +48,14 @@ public:
void handle_message(const mavlink_message_t *msg);
private:
static constexpr size_t LOG_FILEPATH_SIZE = 256; // Buffer size for log file paths
struct LogEntry {
uint16_t id{0xffff};
uint32_t time_utc{};
uint32_t size_bytes{};
FILE *fp{nullptr};
char filepath[60];
char filepath[LOG_FILEPATH_SIZE];
uint32_t offset{};
};
@@ -40,7 +40,7 @@
TEST_CASE("Takeoff and hold position", "[multicopter][vtol]")
{
const float takeoff_altitude = 10.f;
const float altitude_tolerance = 0.1f;
const float altitude_tolerance = 0.2f;
const int delay_seconds = 60.f;
AutopilotTester tester;