fix(mavlink): bound recursion depth in delete_all_logs

Prevent potential stack overflow from symlink loops or deeply nested
directories by capping recursion to 3 levels. Also fixes dot-entry
skipping to use strcmp instead of prefix check, and deduplicates the
filepath construction.
This commit is contained in:
Jacob Dahl 2026-03-06 14:36:34 -09:00 committed by Ramon Roche
parent 7c1dee0b41
commit 8d99569643
2 changed files with 27 additions and 25 deletions

View File

@ -522,9 +522,16 @@ bool MavlinkLogHandler::log_entry_from_id(uint16_t log_id, LogEntry *entry)
return found_entry;
}
void MavlinkLogHandler::delete_all_logs(const char *dir)
void MavlinkLogHandler::delete_all_logs(const char *dir, unsigned depth)
{
//-- Open log directory
// Log structure is log/yyyy-mm-dd/file.ulg (2 levels). Cap recursion to prevent stack overflow.
static constexpr unsigned MAX_DEPTH = 3;
if (depth > MAX_DEPTH) {
PX4_DEBUG("Max depth reached: %s", dir);
return;
}
DIR *dp = opendir(dir);
if (dp == nullptr) {
@ -534,34 +541,29 @@ void MavlinkLogHandler::delete_all_logs(const char *dir)
struct dirent *result = nullptr;
while ((result = readdir(dp))) {
// no more entries?
if (result == nullptr) {
break;
if (strcmp(result->d_name, ".") == 0 || strcmp(result->d_name, "..") == 0) {
continue;
}
if (result->d_type == PX4LOG_DIRECTORY && result->d_name[0] != '.') {
char filepath[PX4_MAX_FILEPATH];
int ret = snprintf(filepath, sizeof(filepath), "%s/%s", dir, result->d_name);
bool path_is_ok = (ret > 0) && (ret < (int)sizeof(filepath));
char filepath[PX4_MAX_FILEPATH];
int ret = snprintf(filepath, sizeof(filepath), "%s/%s", dir, result->d_name);
bool path_is_ok = (ret > 0) && (ret < (int)sizeof(filepath));
if (path_is_ok) {
delete_all_logs(filepath);
if (!path_is_ok) {
continue;
}
if (rmdir(filepath)) {
PX4_DEBUG("Error removing %s", filepath);
}
if (result->d_type == PX4LOG_DIRECTORY) {
delete_all_logs(filepath, depth + 1);
if (rmdir(filepath)) {
PX4_DEBUG("Error removing %s", filepath);
}
}
if (result->d_type == PX4LOG_REGULAR_FILE) {
char filepath[PX4_MAX_FILEPATH];
int ret = snprintf(filepath, sizeof(filepath), "%s/%s", dir, result->d_name);
bool path_is_ok = (ret > 0) && (ret < (int)sizeof(filepath));
if (path_is_ok) {
if (unlink(filepath)) {
PX4_DEBUG("Error unlinking %s", filepath);
}
} else {
if (unlink(filepath)) {
PX4_DEBUG("Error unlinking %s", filepath);
}
}
}

View File

@ -96,7 +96,7 @@ private:
bool log_entry_from_id(uint16_t log_id, LogEntry *entry);
// Log erase
void delete_all_logs(const char *dir);
void delete_all_logs(const char *dir, unsigned depth = 0);
private: