From c661032efc4d6a22ba42f31407ddc330f28b8c4b Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Sun, 19 Jul 2026 02:27:31 +0200 Subject: [PATCH 1/4] Improve website documentation - Improve links & fix dead links - Improve formatting - Improve code snippets (formatting & code) - Fix typos - Consistently use Docusaurus Admonitions for notes --- docs/docs/advanced/cpu-limits.md | 3 ++- docs/docs/advanced/logging.md | 8 ++++---- docs/docs/advanced/memory-customization.md | 4 +++- docs/docs/advanced/simd.md | 12 +++++++---- docs/docs/annotations/index.md | 6 +++--- docs/docs/core/execution-modes.md | 2 +- docs/docs/core/host-functions.md | 5 +++-- docs/docs/core/memory.md | 5 +++-- docs/docs/examples/rust.md | 11 ++++++---- docs/docs/execution/build-time-compiler.md | 18 ++++++++-------- docs/docs/execution/compiler-cache.md | 20 +++++++++--------- docs/docs/execution/runtime-compiler.md | 24 +++++++++++----------- docs/docs/experimental/cli.md | 2 +- docs/docs/experimental/why.md | 2 +- docs/docs/index.md | 4 +++- docs/docs/security/best-practices.md | 10 ++++----- docs/docs/security/overview.md | 4 ++-- docs/docs/wasi/index.md | 21 +++++++++++-------- wasi/README.md | 2 +- 19 files changed, 91 insertions(+), 72 deletions(-) diff --git a/docs/docs/advanced/cpu-limits.md b/docs/docs/advanced/cpu-limits.md index c1f08ec3c..04e60c384 100644 --- a/docs/docs/advanced/cpu-limits.md +++ b/docs/docs/advanced/cpu-limits.md @@ -51,7 +51,7 @@ var thread = new Thread() { } }; thread.start(); -Thread.sleep(200); +thread.join(200); thread.interrupt(); ``` @@ -67,6 +67,7 @@ var future = service.submit(() -> function.apply()); try { future.get(100, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { + future.cancel(true); // handle the failure } ``` diff --git a/docs/docs/advanced/logging.md b/docs/docs/advanced/logging.md index 8d0f73861..50f10caf1 100644 --- a/docs/docs/advanced/logging.md +++ b/docs/docs/advanced/logging.md @@ -5,13 +5,13 @@ title: Logging --- # Logging -For maximum compatibility and to avoid external dependencies we use, by default, the JDK Platform Logging (JEP 264). -You can configure it by providing a `logging.properties` using the `java.util.logging.config.file` property and [here](https://docs.oracle.com/cd/E57471_01/bigData.100/data_processing_bdd/src/rdp_logging_config.html) you can find the possible configurations. +For maximum compatibility and to avoid external dependencies we use, by default, the JDK Platform Logging ([JEP 264](https://openjdk.org/jeps/264)). +The Platform Logging falls back to the [`java.util.logging` API](https://docs.oracle.com/en/java/javase/21/core/java-logging-overview.html) by default. For more advanced configuration scenarios we encourage you to provide an alternative, compatible, adapter: -- [slf4j](https://www.slf4j.org/manual.html#jep264) -- [log4j2](https://logging.apache.org/log4j/2.x/log4j-jpl.html) +- [SLF4J](https://www.slf4j.org/manual.html#jep264) +- [Log4j2](https://logging.apache.org/log4j/2.x/log4j-jpl.html) It's also possible to provide a custom `run.endive.log.Logger` implementation if JDK Platform Logging is not available or doesn't fit. diff --git a/docs/docs/advanced/memory-customization.md b/docs/docs/advanced/memory-customization.md index 9821c8e9b..34e9abcbf 100644 --- a/docs/docs/advanced/memory-customization.md +++ b/docs/docs/advanced/memory-customization.md @@ -35,7 +35,9 @@ var instance = Instance.builder(module).withMemoryFactory(limits -> { }).build(); ``` -> **NOTE:** Since Endive 1.1.0, an optimized memory implementation called `ByteArrayMemory` is also available. We recommend plugging this implementation on all recent OpenJDK systems for enhanced performance. On different Java runtimes (in particular, on Android VMs) you should stick to `ByteBufferMemory`. +:::note +Since Endive 1.1.0, an optimized memory implementation called `ByteArrayMemory` is also available. We recommend plugging this implementation on all recent OpenJDK systems for enhanced performance. On different Java runtimes (in particular, on Android VMs) you should stick to `ByteBufferMemory`. +::: ```java -var instance = Instance.builder(DemoModule.load()). - withMachineFactory(DemoModule::create). - build(); +var instance = Instance.builder(DemoModule.load()) + .withMachineFactory(DemoModule::create) + .build(); var exports = new Demo_ModuleExports(instance); ``` diff --git a/docs/docs/execution/compiler-cache.md b/docs/docs/execution/compiler-cache.md index fcf826766..27e52f74c 100644 --- a/docs/docs/execution/compiler-cache.md +++ b/docs/docs/execution/compiler-cache.md @@ -6,10 +6,6 @@ title: Runtime Compiler Cache # Overview of the Runtime Compiler Cache -:::warning[Security Consideration] -The directory cache stores compiled bytecode on disk without integrity verification. Ensure the cache directory has restrictive permissions (`chmod 700`) and is not writable by untrusted users. Do not share caches across trust boundaries. -::: - The runtime compiler cache lets the Endive runtime compiler store the results of compiling WASM modules to Java bytecode. Subsequent executions can skip compilation and start faster. Use the experimental directory-based cache, or implement the simple `run.endive.compiler.Cache` interface: @@ -25,8 +21,12 @@ The compiler uses the module digest (default SHA-256) as the cache key. For exam ## The Directory Cache +:::warning[Security Consideration] +The directory cache stores compiled bytecode on disk without integrity verification. Ensure the cache directory has restrictive permissions (`chmod 700`) and is not writable by untrusted users. Do not share caches across trust boundaries. +::: + The directory cache stores entries as files under a configured directory. For example, -ff the cache directory is `/cache`, and you store the following cache key: +if the cache directory is `/cache`, and you store the following cache key: `sha-256:KRgyTkCm43c34ksqtA8gmdDw4YCfquC2G0qfIFCpb+w=` @@ -38,7 +38,7 @@ It transforms the key to: * translate characters to be file-system-friendly * use a two-character subdirectory prefix to avoid directory scaling issues -The implementation uses file system atomic moves (write to a temp file, then move to the final location). This makes the cache thread safe and safe to share across processes and avoids partial-write failures. Temp files are written under `/cache/.tmp`. Partially written temp files may be left after a crash; there is no automatic cleanup or eviction. The cache size is not limitedβ€”delete files manually to free disk space. +The implementation uses file system atomic moves (write to a temp file, then move to the final location). This makes the cache thread-safe and safe to share across processes and avoids partial-write failures. Temp files are written under `/cache/.tmp`. Partially written temp files may be left after a crash; there is no automatic cleanup or eviction. The cache size is not limited β€” delete files manually to free disk space. ### Using the Directory Cache @@ -91,11 +91,11 @@ var cache = new DirectoryCache(Files.createTempDirectory("cache")); ```java var module = Parser.parse(new File("your.wasm")); -var instance = Instance.builder(module). - withMachineFactory( +var instance = Instance.builder(module) + .withMachineFactory( MachineFactoryCompiler.builder(module).withCache(cache).compile() - ). - build(); + ) + .build(); ``` -> *Note*: Functions in Wasm can return multiple values, hence the array. This function only returns one value, so we take the first value. +:::note +Functions in Wasm can return multiple values, hence the array. This function only returns one value, so we take the first value. +::: diff --git a/docs/docs/security/best-practices.md b/docs/docs/security/best-practices.md index 95cfd50ed..269ffe73c 100644 --- a/docs/docs/security/best-practices.md +++ b/docs/docs/security/best-practices.md @@ -21,7 +21,7 @@ HostFunction readMemory = (Instance instance, long... args) -> { // Validate bounds BEFORE accessing memory var memory = instance.memory(); - if (offset < 0 || length < 0 || offset + length > memory.pages() * 65536) { + if (offset < 0 || length < 0 || Math.addExact(offset, length) > memory.pages() * 65536) { throw new TrapException("out of bounds memory access"); } @@ -33,7 +33,7 @@ HostFunction readMemory = (Instance instance, long... args) -> { **Key rules:** - Validate all memory offsets and lengths before reading/writing -- Never use Wasm-provided values as array indices without bounds checking +- Never use Wasm-provided values as array indices without bounds checking; keep overflow in mind or use overflow-safe methods such as `Math#addExact` or `Objects#checkFromIndexSize` - Be cautious with string decoding β€” enforce maximum lengths - Avoid exposing file paths, SQL queries, or shell commands derived from Wasm input @@ -47,8 +47,8 @@ WASI file access does not enforce path sandboxing by default. Passing the host f ```java title="Example" var options = WasiOptions.builder() - // Use ZeroFS to restrict access to specific directories - .withDirectory("/guest/data", Path.of("/host/sandboxed/data")) + // Use ZeroFs to restrict access to specific directories + .withDirectory("/guest/data", zeroFs.getPath("/host/sandboxed/data")) .withStdout(myStdout) .withStderr(myStderr) .build(); @@ -80,7 +80,7 @@ See [CPU Limits](/docs/advanced/cpu-limits) for more patterns. The runtime and build-time compilers translate Wasm to JVM bytecode for performance. When running untrusted modules: - **Prefer the interpreter** for maximum sandbox assurance β€” it doesn't generate JVM bytecode -- **Protect compiler cache directories** with restrictive permissions (`chmod 700`) if using the directory cache +- **Protect compiler cache directories** with restrictive permissions (`chmod 700`) if using the [directory cache](/docs/execution/compiler-cache/#the-directory-cache) - **Set JVM heap limits** when compiling large untrusted modules to prevent resource exhaustion ## Dependency Supply Chain diff --git a/docs/docs/security/overview.md b/docs/docs/security/overview.md index a9bfcdc88..ed35bb4c3 100644 --- a/docs/docs/security/overview.md +++ b/docs/docs/security/overview.md @@ -47,13 +47,13 @@ The critical trust boundary is between **Wasm guest code** and **host functions* - **CPU limits**: Wasm modules can execute infinite loops. The host must enforce timeouts (see [CPU Limits](/docs/advanced/cpu-limits)). - **Memory growth limits**: Modules can request memory growth up to the declared maximum. The host should set appropriate limits. - **Post-compilation verification**: The build-time and runtime compilers translate Wasm to JVM bytecode without a separate verification pass. For maximum assurance with untrusted code, prefer the interpreter. -- **Cache integrity**: The directory-based compiler cache does not verify bytecode integrity on load. Protect cache directories with restrictive permissions. +- **Cache integrity**: The [directory-based compiler cache](/docs/execution/compiler-cache/#the-directory-cache) does not verify bytecode integrity on load. Protect cache directories with restrictive permissions. ## WASI and Capability-Based Security When using WASI, the host controls what capabilities the guest receives: -- **Filesystem access** is opt-in. Use a virtual filesystem (e.g., ZeroFS) to restrict access to specific directories. +- **Filesystem access** is opt-in. Use a virtual filesystem (e.g., [ZeroFs](https://github.com/roastedroot/zerofs)) to restrict access to specific directories. - **Environment variables** and **command-line arguments** are explicitly passed by the host. - **Standard I/O** streams are host-controlled. diff --git a/docs/docs/wasi/index.md b/docs/docs/wasi/index.md index 856555b3e..39aaf2448 100644 --- a/docs/docs/wasi/index.md +++ b/docs/docs/wasi/index.md @@ -6,7 +6,7 @@ title: Wasi Preview 1 # WASI Preview 1 :::warning[Security Consideration] -WASI file access does not enforce path sandboxing by default. Always use a virtual filesystem (e.g., ZeroFS or JimFS) to restrict guest access to pre-opened directories. Passing the host filesystem directly exposes all files the JVM process can access. See [Security Best Practices](/docs/security/best-practices). +WASI file access does not enforce path sandboxing by default. Always use a virtual filesystem (e.g., [ZeroFs](https://github.com/roastedroot/zerofs) or [Jimfs](https://github.com/google/jimfs)) to restrict guest access to pre-opened directories. Passing the host filesystem directly exposes all files the JVM process can access. See [Security Best Practices](/docs/security/best-practices). ::: Notice that it is always possible to connect standard output, standard input and standard error to the system's real streams. -For instance, in the case of stdout, you would write: +For instance, you would write: ```java var wasi = WasiOptions.builder().withStdout(System.out).withStderr(System.err).withStdin(System.in).build(); @@ -163,7 +165,10 @@ var wasi = WasiOptions.builder().withArguments(List.of("executable-name", "--mor To expose environment variables to your WASI module you can list them in the options: ```java -var wasi = WasiOptions.builder().withEnvironment("ENV_ONE_KEY", "my-one-key-value").withEnvironment("ENV_TWO_KEY", "my-two-key-value").build(); +var wasi = WasiOptions.builder() + .withEnvironment("ENV_ONE_KEY", "my-one-key-value") + .withEnvironment("ENV_TWO_KEY", "my-two-key-value") + .build(); ``` ## disk @@ -196,7 +201,7 @@ try (FileSystem fs = Jimfs.newFileSystem(Configuration.unix().toBuilder().setAtt ## Supported Features -If your module calls a wasi function that we don't support, or uses a feature that we don't support, we will throw a `WasmRuntimeException`. +If your module calls a WASI function that we don't support, or uses a feature that we don't support, we will throw a `WasmRuntimeException`. For the most up-to-date info, and to see what specific functions we support, see the [WasiPreview1.java](https://github.com/bytecodealliance/endive/blob/main/wasi/src/main/java/run/endive/wasi/WasiPreview1.java) and the following table: diff --git a/wasi/README.md b/wasi/README.md index 7d462dd61..72051061f 100644 --- a/wasi/README.md +++ b/wasi/README.md @@ -5,4 +5,4 @@ This library contains code for instantiating and running WASI modules. by many of the compilers out there. This library implements the widely-available version 0.1 of the spec, also known as `wasip1`. -For further details see the [corresponding docs](https://endive.run/docs/usage/wasi) section +For further details see the [corresponding docs](https://endive.run/docs/usage/wasi) section. From 56aebec68d94111bbfacb1ca11c2b3a1aeec4675 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Tue, 21 Jul 2026 18:15:18 +0200 Subject: [PATCH 2/4] Reword memory customization --- docs/docs/advanced/memory-customization.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/docs/advanced/memory-customization.md b/docs/docs/advanced/memory-customization.md index 34e9abcbf..c5bb30fe7 100644 --- a/docs/docs/advanced/memory-customization.md +++ b/docs/docs/advanced/memory-customization.md @@ -31,12 +31,14 @@ It's possible to provide a custom implementation of the entire Memory used by th ```java var instance = Instance.builder(module).withMemoryFactory(limits -> { - return new ByteArrayMemory(limits); + return new MyCustomMemory(limits); }).build(); ``` :::note -Since Endive 1.1.0, an optimized memory implementation called `ByteArrayMemory` is also available. We recommend plugging this implementation on all recent OpenJDK systems for enhanced performance. On different Java runtimes (in particular, on Android VMs) you should stick to `ByteBufferMemory`. +Endive provides two built-in Memory implementations: +- `ByteArrayMemory`: An optimized memory implementation, recommended for recent OpenJDK systems +- `ByteBufferMemory`: Recommended for different Java runtimes (in particular, on Android VMs) ::: ```java -var instance = Instance.builder(DemoModule.load()) - .withMachineFactory(DemoModule::create) - .build(); +var instance = Instance.builder(DemoModule.load()). + withMachineFactory(DemoModule::create). + build(); var exports = new Demo_ModuleExports(instance); ``` diff --git a/docs/docs/execution/compiler-cache.md b/docs/docs/execution/compiler-cache.md index 27e52f74c..5cd44933d 100644 --- a/docs/docs/execution/compiler-cache.md +++ b/docs/docs/execution/compiler-cache.md @@ -91,11 +91,11 @@ var cache = new DirectoryCache(Files.createTempDirectory("cache")); ```java var module = Parser.parse(new File("your.wasm")); -var instance = Instance.builder(module) - .withMachineFactory( +var instance = Instance.builder(module). + withMachineFactory( MachineFactoryCompiler.builder(module).withCache(cache).compile() - ) - .build(); + ). + build(); ```