GCC Code Coverage Report


Directory: Os/
File: SandboxedFile.cpp
Date: 2026-09-23 21:11:56
Exec Total Coverage
Lines: 43 60 71.7%
Functions: 10 18 55.6%
Branches: 17 21 81.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title Os/SandboxedFile.cpp
3 // \brief Implementation of directory-sandboxed file wrapper
4 // ======================================================================
5 #include <Fw/Types/Assert.hpp>
6 #include <Fw/Types/StringUtils.hpp>
7 #include <Os/SandboxedFile.hpp>
8 #include <cstring>
9
10 namespace Os {
11
12 // Fail-closed: open() returns OUTSIDE_SANDBOX until configure() is called
13
1/1
✓ Branch 7 taken 11 times.
11 SandboxedFile::SandboxedFile() : m_file(), m_allowedDirectory(""), m_configured(false) {}
14
15 22 SandboxedFile::~SandboxedFile() {
16
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
11 if (m_file.isOpen()) {
17 ✗ m_file.close();
18 }
19 22 }
20
21 8 void SandboxedFile::configure(const char* allowedDirectory) {
22 8 FW_ASSERT(allowedDirectory != nullptr);
23 8 FW_ASSERT(!m_file.isOpen());
24
25 // Resolve the allowed directory (relative paths resolve against CWD)
26 8 char resolved[FilePathUtils::MAX_PATH_LENGTH];
27 const FilePathUtils::Status resolveStatus =
28
1/1
✓ Branch 1 taken 8 times.
8 FilePathUtils::resolveFromCwd(allowedDirectory, resolved, sizeof(resolved));
29 8 FW_ASSERT(resolveStatus == FilePathUtils::VALID);
30
31 // Ensure trailing '/'
32
1/1
✓ Branch 1 taken 8 times.
8 const FwSizeType resolvedLen = Fw::StringUtils::string_length(resolved, FilePathUtils::MAX_PATH_LENGTH);
33 8 FW_ASSERT(resolvedLen > 0);
34 8 FW_ASSERT(resolvedLen + 2 <= FilePathUtils::MAX_PATH_LENGTH);
35
1/2
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
8 if (resolved[resolvedLen - 1] != '/') {
36 8 resolved[resolvedLen] = '/';
37 8 resolved[resolvedLen + 1] = '\0';
38 }
39
40
1/1
✓ Branch 6 taken 8 times.
8 m_allowedDirectory = resolved;
41 8 m_configured = true;
42 8 }
43
44 2 bool SandboxedFile::isConfigured() const {
45
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 return m_configured;
46 }
47
48 10 Os::FileInterface::Status SandboxedFile::open(const char* path,
49 Os::FileInterface::Mode mode,
50 Os::FileInterface::OverwriteType overwrite) {
51 10 FW_ASSERT(path != nullptr);
52
53
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 8 times.
10 if (!m_configured) {
54 2 return Os::FileInterface::Status::OUTSIDE_SANDBOX;
55 }
56
57 // Resolve path against CWD then check containment
58 8 char resolvedPath[FilePathUtils::MAX_PATH_LENGTH];
59
1/1
✓ Branch 1 taken 8 times.
8 const FilePathUtils::Status resolveStatus = FilePathUtils::resolveFromCwd(path, resolvedPath, sizeof(resolvedPath));
60
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (resolveStatus != FilePathUtils::VALID) {
61 2 return Os::FileInterface::Status::OUTSIDE_SANDBOX;
62 }
63
64
3/3
✓ Branch 7 taken 6 times.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 3 times.
6 if (FilePathUtils::checkContainment(resolvedPath, m_allowedDirectory.toChar()) != FilePathUtils::VALID) {
65 3 return Os::FileInterface::Status::OUTSIDE_SANDBOX;
66 }
67
68
1/1
✓ Branch 5 taken 3 times.
3 return m_file.open(resolvedPath, mode, overwrite);
69 }
70
71 3 void SandboxedFile::close() {
72 3 m_file.close();
73 3 }
74
75 8 bool SandboxedFile::isOpen() const {
76 8 return m_file.isOpen();
77 }
78
79 ✗ Os::FileInterface::Status SandboxedFile::size(FwSizeType& size_result) {
80 ✗ return m_file.size(size_result);
81 }
82
83 ✗ Os::FileInterface::Status SandboxedFile::position(FwSizeType& position_result) {
84 ✗ return m_file.position(position_result);
85 }
86
87 ✗ Os::FileInterface::Status SandboxedFile::preallocate(FwSizeType offset, FwSizeType length) {
88 ✗ return m_file.preallocate(offset, length);
89 }
90
91 ✗ Os::FileInterface::Status SandboxedFile::seek(FwSignedSizeType offset, Os::FileInterface::SeekType seekType) {
92 ✗ return m_file.seek(offset, seekType);
93 }
94
95 ✗ Os::FileInterface::Status SandboxedFile::flush() {
96 ✗ return m_file.flush();
97 }
98
99 1 Os::FileInterface::Status SandboxedFile::read(U8* buffer, FwSizeType& size, Os::FileInterface::WaitType wait) {
100 1 return m_file.read(buffer, size, wait);
101 }
102
103 ✗ Os::FileInterface::Status SandboxedFile::read(U8* buffer, FwSizeType& size) {
104 ✗ return m_file.read(buffer, size);
105 }
106
107 1 Os::FileInterface::Status SandboxedFile::write(const U8* buffer, FwSizeType& size, Os::FileInterface::WaitType wait) {
108 1 return m_file.write(buffer, size, wait);
109 }
110
111 ✗ Os::FileInterface::Status SandboxedFile::write(const U8* buffer, FwSizeType& size) {
112 ✗ return m_file.write(buffer, size);
113 }
114
115 ✗ Os::FileInterface::Status SandboxedFile::calculateCrc(U32& crc) {
116 ✗ return m_file.calculateCrc(crc);
117 }
118
119 2 const char* SandboxedFile::getSandboxDirectory() const {
120 2 return m_allowedDirectory.toChar();
121 }
122
123 } // namespace Os
124