add virtual filesystem with path sandboxing and quotas (milestone 7 complete)

This commit is contained in:
2026-01-18 15:04:46 +01:00
parent be663282d7
commit 2bb083fd7d
6 changed files with 1420 additions and 1 deletions

View File

@@ -18,6 +18,7 @@ add_library(mosis-sandbox STATIC
../src/main/cpp/sandbox/timer_manager.cpp
../src/main/cpp/sandbox/json_api.cpp
../src/main/cpp/sandbox/crypto_api.cpp
../src/main/cpp/sandbox/virtual_fs.cpp
)
target_include_directories(mosis-sandbox PUBLIC
../src/main/cpp/sandbox

View File

@@ -9,6 +9,7 @@
#include "timer_manager.h"
#include "json_api.h"
#include "crypto_api.h"
#include "virtual_fs.h"
#include <filesystem>
#include <fstream>
#include <sstream>
@@ -1074,6 +1075,190 @@ bool Test_SecureMathRandom(std::string& error_msg) {
return true;
}
//=============================================================================
// MILESTONE 7: VIRTUAL FILESYSTEM TESTS
//=============================================================================
bool Test_VirtualFSReadWrite(std::string& error_msg) {
std::string test_root = "test_vfs_app";
mosis::VirtualFS vfs("test.app", test_root);
std::string err;
// Write a file
EXPECT_TRUE(vfs.Write("/data/test.txt", "Hello World", err));
// Read it back
auto content = vfs.Read("/data/test.txt", err);
EXPECT_TRUE(content.has_value());
EXPECT_TRUE(*content == "Hello World");
// Cleanup
vfs.ClearAll();
return true;
}
bool Test_VirtualFSBlocksTraversal(std::string& error_msg) {
std::string test_root = "test_vfs_app";
mosis::VirtualFS vfs("test.app", test_root);
std::string err;
// Should reject traversal
EXPECT_FALSE(vfs.Write("/data/../../../etc/passwd", "hack", err));
EXPECT_TRUE(err.find("traversal") != std::string::npos ||
err.find("invalid") != std::string::npos);
// Should reject paths without valid prefix
err.clear();
EXPECT_FALSE(vfs.Write("/etc/passwd", "hack", err));
vfs.ClearAll();
return true;
}
bool Test_VirtualFSEnforcesQuota(std::string& error_msg) {
std::string test_root = "test_vfs_app";
mosis::VirtualFSLimits limits;
limits.max_quota_bytes = 1024; // 1 KB quota for testing
mosis::VirtualFS vfs("test.app", test_root, limits);
std::string err;
// Write should succeed
std::string small_data(500, 'a');
EXPECT_TRUE(vfs.Write("/data/file1.txt", small_data, err));
// Second write should fail (exceeds quota)
std::string large_data(600, 'b');
EXPECT_FALSE(vfs.Write("/data/file2.txt", large_data, err));
EXPECT_TRUE(err.find("quota") != std::string::npos);
vfs.ClearAll();
return true;
}
bool Test_VirtualFSCleansUpTemp(std::string& error_msg) {
std::string test_root = "test_vfs_app";
mosis::VirtualFS vfs("test.app", test_root);
std::string err;
// Write to temp
EXPECT_TRUE(vfs.Write("/temp/session.txt", "temp data", err));
EXPECT_TRUE(vfs.Exists("/temp/session.txt"));
// Clear temp
vfs.ClearTemp();
// Should be gone
EXPECT_FALSE(vfs.Exists("/temp/session.txt"));
vfs.ClearAll();
return true;
}
bool Test_VirtualFSList(std::string& error_msg) {
std::string test_root = "test_vfs_app";
mosis::VirtualFS vfs("test.app", test_root);
std::string err;
// Create some files
vfs.Write("/data/file1.txt", "content1", err);
vfs.Write("/data/file2.txt", "content2", err);
vfs.MakeDir("/data/subdir", err);
// List directory
auto files = vfs.List("/data/", err);
EXPECT_TRUE(files.has_value());
EXPECT_TRUE(files->size() == 3);
vfs.ClearAll();
return true;
}
bool Test_VirtualFSStat(std::string& error_msg) {
std::string test_root = "test_vfs_app";
mosis::VirtualFS vfs("test.app", test_root);
std::string err;
// Write a file
vfs.Write("/data/test.txt", "Hello", err);
// Get stat
auto stat = vfs.Stat("/data/test.txt", err);
EXPECT_TRUE(stat.has_value());
EXPECT_TRUE(stat->size == 5);
EXPECT_FALSE(stat->is_dir);
// Directory stat
vfs.MakeDir("/data/subdir", err);
auto dir_stat = vfs.Stat("/data/subdir", err);
EXPECT_TRUE(dir_stat.has_value());
EXPECT_TRUE(dir_stat->is_dir);
vfs.ClearAll();
return true;
}
bool Test_VirtualFSLuaIntegration(std::string& error_msg) {
SandboxContext ctx = TestContext();
LuaSandbox sandbox(ctx);
std::string test_root = "test_vfs_lua";
mosis::VirtualFS vfs("test.app", test_root);
mosis::RegisterVirtualFS(sandbox.GetState(), &vfs);
std::string script = R"(
-- Write and read
local ok, err = fs.write("/data/test.txt", "Hello from Lua")
assert(ok, "write failed: " .. (err or ""))
local content, err = fs.read("/data/test.txt")
assert(content == "Hello from Lua", "content mismatch: " .. (content or "nil"))
-- Check exists
assert(fs.exists("/data/test.txt"), "file should exist")
assert(not fs.exists("/data/nonexistent.txt"), "file should not exist")
-- Stat
local stat = fs.stat("/data/test.txt")
assert(stat.size == 14, "size should be 14, got " .. tostring(stat.size))
assert(not stat.isDir, "should not be dir")
)";
bool ok = sandbox.LoadString(script, "vfs_test");
vfs.ClearAll();
if (!ok) {
error_msg = "Lua test failed: " + sandbox.GetLastError();
return false;
}
return true;
}
bool Test_VirtualFSMaxFileSize(std::string& error_msg) {
std::string test_root = "test_vfs_app";
mosis::VirtualFSLimits limits;
limits.max_file_size = 100; // 100 bytes max
limits.max_quota_bytes = 10000; // Large quota
mosis::VirtualFS vfs("test.app", test_root, limits);
std::string err;
// Small file should succeed
EXPECT_TRUE(vfs.Write("/data/small.txt", std::string(50, 'a'), err));
// Large file should fail
EXPECT_FALSE(vfs.Write("/data/large.txt", std::string(200, 'b'), err));
EXPECT_TRUE(err.find("size") != std::string::npos);
vfs.ClearAll();
return true;
}
//=============================================================================
// MAIN
//=============================================================================
@@ -1176,6 +1361,16 @@ int main(int argc, char* argv[]) {
harness.AddTest("CryptoHMAC", Test_CryptoHMAC);
harness.AddTest("SecureMathRandom", Test_SecureMathRandom);
// Milestone 7: Virtual Filesystem
harness.AddTest("VirtualFSReadWrite", Test_VirtualFSReadWrite);
harness.AddTest("VirtualFSBlocksTraversal", Test_VirtualFSBlocksTraversal);
harness.AddTest("VirtualFSEnforcesQuota", Test_VirtualFSEnforcesQuota);
harness.AddTest("VirtualFSCleansUpTemp", Test_VirtualFSCleansUpTemp);
harness.AddTest("VirtualFSList", Test_VirtualFSList);
harness.AddTest("VirtualFSStat", Test_VirtualFSStat);
harness.AddTest("VirtualFSLuaIntegration", Test_VirtualFSLuaIntegration);
harness.AddTest("VirtualFSMaxFileSize", Test_VirtualFSMaxFileSize);
// Run tests
auto results = harness.Run(filter);