Skip to content

WIP Plugin support#38

Draft
coco875 wants to merge 4 commits intoSteel-Foundation:devfrom
coco875:plugin-support
Draft

WIP Plugin support#38
coco875 wants to merge 4 commits intoSteel-Foundation:devfrom
coco875:plugin-support

Conversation

@coco875
Copy link
Copy Markdown
Contributor

@coco875 coco875 commented Dec 28, 2025

have generate a basic implementation of plugin with abi_stable

things who are needed to discuss

  • api with ferrumc
  • split in a separte repo (currently steel-plugin-api depend on nothing so we can make as repo where plugin a link against it and would work with both steel and ferrumc without changing nothing)
  • maybe start with registries api to get id ?

@coco875 coco875 changed the base branch from master to dev December 28, 2025 04:26
@coco875 coco875 marked this pull request as draft December 28, 2025 04:26
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Dec 28, 2025

Greptile Summary

This PR implements a plugin system for Steel using abi_stable for FFI-safe dynamic library loading, enabling custom chunk generators through a new steel-plugin-api crate. The implementation adds plugin loading from a plugins/ directory at server startup, with plugins providing chunk generators that integrate into the existing world generation pipeline.

Key Changes:

  • Created steel-plugin-api crate with FFI-safe traits (PluginChunkGenerator, ChunkAccessTrait) and types using abi_stable
  • Added PluginManager that loads .so/.dll/.dylib files and extracts chunk generators
  • Implemented PluginChunkGeneratorWrapper to adapt plugin generators to internal ChunkGenerator trait
  • Added ChunkGeneratorType::Plugin variant and threaded generator option through Server, World, and ChunkMap initialization
  • Included example plugin (steel-plugin-example) that generates stone terrain with sine wave patterns

Critical Issues Found:

  • Security vulnerability: Plugin loader has no sandboxing or trust verification - any .so/.dll/.dylib in plugins/ directory executes with full server privileges
  • Memory safety issue: ChunkAccessWrapper performs no bounds checking on coordinates, allowing plugins to write outside chunk boundaries
  • Logic bug: take_first_generator() and take_all_chunk_generators() consume generators using Arc::try_unwrap, making them single-use only
  • Crash risk: Example plugin uses assert!(y < 16) which will panic and crash the server on floating point edge cases

Confidence Score: 2/5

  • This PR has critical security and memory safety issues that make it unsafe to merge
  • The plugin system loads untrusted native code without sandboxing, has missing bounds checking that could cause memory corruption, contains a generator consumption bug that breaks reusability, and includes an example that can crash the server. While the FFI architecture using abi_stable is sound, the implementation has multiple bugs that need resolution before production use.
  • Pay close attention to steel/src/plugin/mod.rs (security), steel-core/src/chunk/plugin_chunk_generator.rs (bounds checking), and steel-plugin-example/src/lib.rs (panic handling)

Important Files Changed

Filename Overview
steel-plugin-api/src/lib.rs new FFI-safe plugin API using abi_stable for chunk generation, well-structured trait definitions
steel-plugin-example/src/lib.rs example stone world generator with sine wave terrain, has panic risk from unchecked assert and hardcoded block IDs
steel/src/plugin/mod.rs plugin manager loads .so/.dll/.dylib files, has security issues (no sandboxing) and generator consumption bug
steel-core/src/chunk/plugin_chunk_generator.rs wrapper adapting plugin generators to internal trait, missing bounds checking allows out-of-bounds writes
steel/src/main.rs integrated plugin loading at startup, loads from plugins/ directory and uses first generator if available

Sequence Diagram

sequenceDiagram
    participant Main as steel/main.rs
    participant PM as PluginManager
    participant Lib as Plugin .so/.dll
    participant API as Plugin API
    participant Server as SteelServer
    participant World as World
    participant ChunkMap as ChunkMap
    participant Wrapper as PluginChunkGeneratorWrapper
    participant Plugin as Plugin Generator

    Main->>PM: new()
    Main->>PM: load_plugins_from_directory("plugins/")
    PM->>Lib: load_from_file()
    Lib-->>PM: PluginModule_Ref
    PM->>Lib: get_metadata()
    Lib-->>PM: PluginMetadata
    PM->>Lib: get_chunk_generators()
    Lib-->>PM: RVec<PluginChunkGenerator_TO>
    PM->>PM: store in LoadedPlugin
    
    Main->>PM: take_first_generator()
    PM->>PM: Arc::try_unwrap()
    PM-->>Main: Option<ChunkGeneratorType::Plugin>
    
    Main->>Server: new_with_generator(generator)
    Server->>World: new_with_generator(generator)
    World->>ChunkMap: new_with_generator(generator)
    ChunkMap->>ChunkMap: store in WorldGenContext
    
    Note over ChunkMap: During chunk generation
    ChunkMap->>Wrapper: fill_from_noise(chunk)
    Wrapper->>Wrapper: create_ffi_chunk_access()
    Wrapper->>Plugin: fill_from_noise(ffi_chunk)
    Plugin->>API: set_relative_block(x, y, z, block)
    API->>Wrapper: ChunkAccessWrapper::set_relative_block()
    Wrapper->>ChunkMap: internal set_relative_block()
Loading

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (5)

  1. steel-plugin-example/src/lib.rs, line 47 (link)

    logic: assert! will panic and crash the server if the calculation produces y >= 16, which could happen due to floating point precision

  2. steel/src/plugin/mod.rs, line 118-132 (link)

    logic: consuming generators with std::mem::take and Arc::try_unwrap means plugins can only be used once - if this is called multiple times, subsequent calls get empty generators

    is the intent to consume the generators so they can only be used once, or should plugins remain usable after initialization?

  3. steel/src/plugin/mod.rs, line 79-80 (link)

    logic: loading plugins from untrusted .so/.dll/.dylib files allows arbitrary code execution with full server privileges - plugins should be sandboxed or require explicit trust

  4. steel-core/src/chunk/plugin_chunk_generator.rs, line 45-62 (link)

    logic: no bounds checking on x, y, z - plugins can write outside chunk boundaries, causing memory corruption or panics

  5. steel-plugin-example/src/lib.rs, line 20 (link)

    style: hardcoded block ID 1 may not match actual stone ID in the registry - should query from registry or make configurable

18 files reviewed, 5 comments

Edit Code Review Agent Settings | Greptile

@github-actions
Copy link
Copy Markdown

This pull request has conflicts with the base branch "master". Please resolve those so we can test out your changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants