Skip to content

Commit 3ed7fb5

Browse files
samuelcolvinclaude
andauthored
Mounting filesystems (#305)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a5e2266 commit 3ed7fb5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+9373
-284
lines changed

.github/workflows/ci.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,39 @@ jobs:
146146
# test uv run exercise script
147147
- run: uv run crates/monty-python/exercise.py
148148

149+
test-rust-os:
150+
name: test rust on ${{ matrix.os }}
151+
strategy:
152+
fail-fast: false
153+
matrix:
154+
include:
155+
- os: macos-latest
156+
- os: windows-latest
157+
158+
runs-on: ${{ matrix.os }}
159+
160+
steps:
161+
- uses: actions/checkout@v6
162+
163+
- uses: dtolnay/rust-toolchain@stable
164+
- uses: Swatinem/rust-cache@v2
165+
with:
166+
cache-on-failure: true
167+
168+
- uses: actions/setup-python@v6
169+
with:
170+
python-version: "3.14"
171+
172+
# don't use .venv python in CI
173+
- name: Remove cargo config (Unix)
174+
if: runner.os != 'Windows'
175+
run: rm .cargo/config.toml
176+
- name: Remove cargo config (Windows)
177+
if: runner.os == 'Windows'
178+
run: Remove-Item .cargo/config.toml
179+
180+
- run: cargo test -p monty --features ref-count-panic
181+
149182
bench-test:
150183
runs-on: ubuntu-latest
151184

@@ -225,6 +258,7 @@ jobs:
225258
needs:
226259
- lint
227260
- test-rust
261+
- test-rust-os
228262
- test-python
229263
- bench-test
230264
- fuzz

CLAUDE.md

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,23 @@ Project goals:
1212
- **Performance**: Fast execution through compile-time optimizations and efficient memory layout
1313
- **Simplicity**: Clean, understandable implementation focused on a Python subset
1414
- **Snapshotting and iteration**: Plan is to allow code to be iteratively executed and snapshotted at each function call
15+
- **Cross-platform**: Runs on Linux, macOS, and Windows (and any other OS that can run Rust)
1516
- Targets the latest stable version of Python, currently Python 3.14
1617

18+
## Cross-Platform Requirements
19+
20+
Monty must work identically on Linux, macOS, and Windows. Within the Monty sandbox,
21+
paths always use POSIX/Linux-style forward slashes (`/`) regardless of the host OS.
22+
The `MountTable` handles translating between virtual POSIX paths and host-native paths.
23+
24+
Key rules:
25+
- **Virtual paths** are always POSIX-style (`/mnt/data/file.txt`), never Windows-style
26+
- **Host paths** use `std::path::Path`/`PathBuf` which handles OS differences automatically
27+
- Avoid `#[cfg(unix)]`-only code in the main crate — all features must work on all platforms
28+
- Tests in `crates/monty/tests/` should be cross-platform; use helper functions for
29+
OS-specific APIs like symlink creation (see `symlink_file`/`symlink_dir` in `fs_security.rs`)
30+
- CI runs `cargo test -p monty --features ref-count-panic` on Linux, macOS, and Windows
31+
1732
## Important Security Notice
1833

1934
It's ABSOLUTELY CRITICAL that there's no way for code run in a Monty sandbox to access the host filesystem, or environment or to in any way "escape the sandbox".
@@ -37,6 +52,27 @@ Possible security risks to consider:
3752
* information leakage via timing or error messages
3853
* Python/Javascript/Rust APIs that accidentally allow developers to expose their host to monty code
3954

55+
## Filesystem Mounts (`crates/monty/src/fs/`)
56+
57+
The `MountTable` allows mounting real host directories into the sandbox at virtual paths,
58+
with configurable access modes (ReadWrite, ReadOnly, OverlayMemory).
59+
60+
**CRITICAL SECURITY INVARIANT:** The monty runtime MUST NEVER read, write, or
61+
obtain any information about any file or directory outside the specific directory
62+
that is mounted. This is enforced by:
63+
64+
- Path canonicalization after mapping virtual → host paths
65+
- Boundary checks verifying canonical paths remain within the mount
66+
- Symlink resolution that rejects links pointing outside the mount
67+
- Virtual-space normalization that prevents `..` escape
68+
- `Resolve` and `Absolute` returning virtual paths, never host paths
69+
- Null byte rejection in all paths
70+
71+
All path resolution goes through `fs::path_security::resolve_path()` which is
72+
the sole security boundary. **Changes to `path_security.rs` require careful security review.**
73+
74+
`heap.rs` and `path_security.rs` are the two most security-critical files in the codebase.
75+
4076
## Bytecode VM Architecture
4177

4278
Monty is implemented as a bytecode VM, same as CPython.
@@ -492,26 +528,6 @@ Container types (`List`, `Tuple`, `Dict`) also have `clone_with_heap()` methods.
492528

493529
**Resource limits**: When resource limits (allocations, memory, time) are exceeded, execution terminates with a `ResourceError`. No guarantees are made about the state of the heap or reference counts after a resource limit is exceeded. The heap may contain orphaned objects with incorrect refcounts. This is acceptable because resource exhaustion is a terminal error - the execution context should be discarded.
494530

495-
## NOTES
496-
497-
ALWAYS consider code quality when adding new code, if functions are getting too complex or code is duplicated, move relevant logic to a new file.
498-
Make sure functions are added in the most logical place, e.g. as methods on a struct where appropriate.
499-
500-
The code should follow the "newspaper" style where public and primary functions are at the top of the file, followed by private functions and utilities.
501-
ALWAYS put utility, private functions and "sub functions" underneath the function they're used in.
502-
503-
It is important to the long term health of the project and maintainability of the codebase that code is well structured and organized, this is very important.
504-
505-
ALWAYS run `make format-rs` and `make lint-rs` after making changes to rust code and fix all suggestions to maintain code quality.
506-
507-
ALWAYS run `make lint-py` after making changes to python code and fix all suggestions to maintain code quality.
508-
509-
ALWAYS update this file when it is out of date.
510-
511-
NEVER add imports anywhere except at the top of the file, this applies to both python and rust.
512-
513-
NEVER write `unsafe` code, if you think you need to write unsafe code, explicitly ask the user or leave a `todo!()` with a suggestion and explanation.
514-
515531
## JavaScript Package (`monty-js`)
516532

517533
The JavaScript package provides Node.js bindings for the Monty interpreter via napi-rs, located in `crates/monty-js/`.
@@ -585,3 +601,25 @@ npm test
585601
- Tests use [ava](https://github.com/avajs/ava) and live in `crates/monty-js/__test__/`
586602
- Tests are written in TypeScript
587603
- Follow the existing test style in the `__test__/` directory
604+
605+
## NOTES
606+
607+
ALWAYS consider code quality when adding new code, if functions are getting too complex or code is duplicated, move relevant logic to a new file.
608+
Make sure functions are added in the most logical place, e.g. as methods on a struct where appropriate.
609+
610+
The code should follow the "newspaper" style where public and primary functions are at the top of the file, followed by private functions and utilities.
611+
ALWAYS put utility, private functions and "sub functions" underneath the function they're used in.
612+
613+
It is important to the long term health of the project and maintainability of the codebase that code is well structured and organized, this is very important.
614+
615+
ALWAYS run `make format-rs` and `make lint-rs` after making changes to rust code and fix all suggestions to maintain code quality.
616+
617+
ALWAYS run `make lint-py` after making changes to python code and fix all suggestions to maintain code quality.
618+
619+
ALWAYS update this file when it is out of date.
620+
621+
NEVER add imports anywhere except at the top of the file, this applies to both python and rust.
622+
623+
NEVER write `unsafe` code, if you think you need to write unsafe code, explicitly ask the user or leave a `todo!()` with a suggestion and explanation.
624+
625+
When you get asked a question like "Is X really the best approach" ANSWER THE QUESTION! don't try to make a chance based on a perceived instruction in the question!

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/monty-cli/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@ monty = { path = "../monty" }
2121
monty_type_checking = { path = "../monty-type-checking" }
2222
rustyline = "15"
2323

24+
[dev-dependencies]
25+
tempfile = "3"
26+
2427
[lints]
2528
workspace = true

0 commit comments

Comments
 (0)