Skip to content

fix: memory safety and file handle leaks - #13

Open
Swissola wants to merge 6 commits into
geo-tp:mainfrom
Swissola:fix/memory-safety-file-handles
Open

fix: memory safety and file handle leaks#13
Swissola wants to merge 6 commits into
geo-tp:mainfrom
Swissola:fix/memory-safety-file-handles

Conversation

@Swissola

Copy link
Copy Markdown

Summary

Five independent safety fixes found during code review. Each is a self-contained change with no functional impact on normal operation — all address edge-case crashes or undefined behaviour.

  • MakeHexUtils.cppstrcpy replaced with strncpy (+ explicit null terminator) when copying a line into the 1024-byte m_bufr. A .ir file line longer than 1023 bytes would overflow the buffer.
  • FileRemoteCommand.hoperator== raw-data loop was bounded by the hardcoded literal 20 instead of lhs.rawDataSize. For commands with >20 samples the comparison silently stopped early; for commands with <20 it read past the allocated array.
  • FileService.cppstd::stoi / std::stof on the frequency: and duty_cycle: fields throw std::invalid_argument / std::out_of_range on malformed .ir files. Wrapped in try/catch with sensible defaults (38 kHz, 0.33 duty cycle).
  • SdService.cppisFile() called f.close() on the directory path but not when the file was not a directory; listElements() did not close dir on the two early-return paths and leaked file handles at the limit break. All paths now explicitly close handles.
  • RemoteRepository.cppFavoriteRemote favoriteRemote; is not zero-initialised in C++ (POD struct). If sscanf partially fills the struct the unused char arrays contain stack garbage. Changed to FavoriteRemote favoriteRemote = {}; to value-initialise all fields to zero before the sscanf.

Test plan

  • Build with PlatformIO — no new warnings or errors
  • Browse IR files including one with a malformed frequency: or duty_cycle: field — no crash
  • Use Favorites (save, list, delete) — no garbled names

🤖 Generated with Claude Code

Swissola and others added 5 commits May 25, 2026 11:29
- MakeHexUtils: strcpy -> strncpy to prevent buffer overflow on lines >1023 chars
- FileRemoteCommand: operator== raw loop bound was hardcoded 20, now uses rawDataSize
- FileService: stoi/stof on malformed .ir files now caught; defaults to 38kHz/0.33 duty
- SdService: explicit File.close() on all paths in isFile() and listElements() to prevent FD exhaustion
- RemoteRepository: FavoriteRemote struct value-initialized (= {}) to zero all fields before sscanf

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extract frequency and duty_cycle parsing into static helpers to reduce
parseInfraredFile cognitive complexity below the 25-unit threshold (was
29 after adding try/catch inline). Named exception type (std::exception)
replaces catch(...) per S2738.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
S1181 flagged catch(const std::exception&) as too broad in both helpers.
std::stoi throws std::invalid_argument (bad input) or std::out_of_range
(value too large); std::stof throws the same two. Catching both explicitly
satisfies the rule without changing behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace stoi/stof + try/catch with strtol/strtof (error via end-pointer,
no catch clauses, removes S1181 entirely). Replace strncpy with snprintf
which always null-terminates (removes strncpy security flag).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
snprintf with "%s" triggers S6494 (prefer std::format). The complete
safe chain for string copy without C++20: std::copy_n + strlen bound.
Add <algorithm> to MakeHexUtils.h for std::min and std::copy_n.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

strlen triggers S5813 (security hotspot). Manual char-by-char loop with
explicit null-terminator avoids all string-function Sonar rules and
makes the <algorithm> include unnecessary.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant