• Stars
    star
    1,628
  • Rank 28,740 (Top 0.6 %)
  • Language
    C
  • License
    Other
  • Created over 7 years ago
  • Updated 11 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

High level Lua bindings to Rust

rlua -- High level bindings between Rust and Lua

Build Status Latest Version API Documentation

Guided Tour

This library is a high level interface between Rust and Lua. Its goal is to be an easy to use, practical, flexible, and safe API between Rust and Lua.

rlua is NOT designed to be a perfect zero cost wrapper over the Lua C API, because such a wrapper cannot maintain the safety guarantees that rlua is designed to have. Every place where the Lua C API may trigger an error longjmp in any way is protected by lua_pcall, and the user of the library is protected from directly interacting with unsafe things like the Lua stack, and there is overhead associated with this safety. However, performance is a focus of the library to the extent possible while maintaining safety, so if you encounter something that is egregiously worse than using the Lua C API directly, or simply something you feel could perform better, feel free to file a bug report.

API stability

Currently, this library follows a pre-1.0 semver, so all API changes should be accompanied by 0.x version bumps. See the Version 1.0 milestone for the work planned to be done before a more stable 1.0 release. There may be breaking changes as these issues are dealt with on the way (the version number will be bumped as needed).

Lua versions supported

As of release 0.18, the version of Lua can be configured at build time using Cargo features. Lua 5.4 is the default. The rlua API stays the same with different Lua versions, though there are a small number of limitations. Lua code may, of course, behave a little differently between the versions.

Only one can be selected at a time, so to select anything other than the default (built-in Lua 5.4) you will need to disable default features.

The available features are:

Cargo feature Lua version
builtin-lua54 Lua 5.4 (source included in package, default)
builtin-lua53 Lua 5.3 (source included in package)
builtin-lua51 Lua 5.1 (source included in package)
system-lua54 Lua 5.4 (installed on host system, found using pkg-config)
system-lua53 Lua 5.3 (installed on host system, found using pkg-config)
system-lua51 Lua 5.1 (installed on host system, found using pkg-config)

At current writing rlua has not been tested with alternative Lua implementations (such as Luajit) which share PUC-Rio Lua's C API, but it is expected that they can be made to work with little if any change to rlua, and support would be welcome.

Loading external C (or other compiled) modules

By default rlua blocks Lua from loading of external modules written in C (or other compiled language) using the Lua C API. To allow this, a couple of things are needed:

  1. Initialise Lua using unsafe_new_with_flags(), and pass non-default flags not including LOAD_WRAPPERS or REMOVE_LOADLIB. This will remove wrappers which block native libraries.

  2. Export the Lua C API symbols so that the library can call Lua C API functions. There are a few options:

    • At time of writing, Rust has an unstable (nightly-only) option to export symbols from an executable: export-executable-symbols

    • Another option is to do it by adding linker flags. For example, on Linux, adding this to a build.rs asks the linker to export symbols: println!("cargo:rustc-link-arg-examples=-Wl,-export-dynamic");

    • Using the system-lua54 (or similar) feature as described above may link against a system shared Lua library instead of building the interpreter into the rlua, making the symbols available.

Other Lua features

Some other features affect how Lua is built (for the builtin versions):

Cargo feature Effect
lua-no-oslib Don't compile the Lua os library at all (builtin Lua libraries).

Safety and Panics

The goal of this library is complete safety by default: it should not be possible to cause undefined behavior with the safe API, even in edge cases. Unsoundness is considered the most serious kind of bug, so if you find the ability to cause UB with this API without unsafe, please file a bug report.

This includes calling functions in the Lua standard library; some unsafe functions are wrapped by default (for example to prevent loading binary modules), but these wrappers can be disabled using one of the unsafe constructors for the Lua object if required for the application.

Another goal of this library is complete protection from panics: currently, it should not be possible for a script to trigger a panic. There ARE however several internal panics in the library, but triggering them is considered a bug. If you find a way to trigger these internal panics, please file a bug report.

Yet another goal of the library is to, in all cases, safely handle panics that are generated inside Rust callbacks. Panic unwinds in Rust callbacks should currently be handled correctly -- the unwind is caught and carried across the Lua API boundary as a regular Lua error in a way that prevents Lua from catching it. This is done by overriding the normal Lua 'pcall' and 'xpcall' functions with custom versions that cannot catch errors that are actually from Rust panics, and by handling panic errors on the receiving Rust side by resuming the panic.

rlua should also be panic safe in another way as well, which is that any Lua instances or handles should remain usable after a user generated panic, and such panics should not break internal invariants or leak Lua stack space. This is mostly important to safely use rlua types in Drop impls, as you should not be using panics for general error handling.

In summary, here is a list of rlua behaviors that should be considered a bug. If you encounter them, a bug report would be very welcome:

  • If you can cause UB with rlua without typing the word "unsafe", this is a bug.
  • If your program panics with a message that contains the string "rlua internal error", this is a bug.
  • The above is true even for the internal panic about running out of stack space! There are a few ways to generate normal script errors by running out of stack, but if you encounter a panic based on running out of stack, this is a bug.
  • When the internal version of Lua is built using the cc crate, and cfg!(debug_assertions) is true, Lua is built with the LUA_USE_APICHECK define set. Any abort caused by this internal Lua API checking is definitely a bug, and is likely to be a soundness bug because without LUA_USE_APICHECK it would likely instead be UB.
  • Lua C API errors are handled by longjmp. All instances where the Lua C API would otherwise longjmp over calling stack frames should be guarded against, except in internal callbacks where this is intentional. If you detect that rlua is triggering a longjmp over your Rust stack frames, this is a bug!
  • If you can somehow handle a panic triggered from a Rust callback in Lua, this is a bug.
  • If you detect that, after catching a panic or during a Drop triggered from a panic, a Lua or handle method is triggering other bugs or there is a Lua stack space leak, this is a bug. rlua instances are supposed to remain fully usable in the face of user generated panics. This guarantee does not extend to panics marked with "rlua internal error" simply because that is already indicative of a separate bug.

Sandboxing and Untrusted Scripts

The API now contains the pieces necessary to implement simple, limited "sandboxing" of Lua scripts by controlling their environment, limiting their allotted VM instructions, and limiting the amount of memory they may allocate.

These features deserve a few words of warning: Do not use them to run untrusted scripts unless you really Know What You Are Doing (tm) (and even then, you probably should not do this).

First, this library contains a huge amount of unsafe code, and I currently would not trust it in a truly security sensitive context. There are almost certainly bugs still lurking in this library! It is surprisingly, fiendishly difficult to use the Lua C API without the potential for unsafety.

Second, properly sandboxing Lua scripts can be quite difficult, much of the stdlib is unsafe, and sometimes in surprising ways. Some information on this can be found here.

Third, PUC-Rio Lua is a C library not really designed to be used with untrusted scripts. Please understand that though PUC-Rio Lua is an extremely well written language runtime, it is still quite a lot of C code, and it is not commonly used with truly malicious scripts. Take a look here and count how many bugs resulted in memory unsafety in the interpreter. Another small example: did you know there is a way to attack Lua tables to cause linear complexity in the table length operator? That this still counts as one VM instruction?

Fourth, if you provide a callback API to scripts, it can be very difficult to secure that API. Do all of your API functions have some maximum runtime? Do any of your API functions allow the script to allocate via Rust? Are there limits on how much they can allocate this way? All callback functions still count as a single VM instruction!

In any case, sandboxing in this way may still be useful to protect against buggy (but non-malicious) scripts, and may even serve as a single layer of a larger security strategy, but please think twice before relying on this to protect you from untrusted Lua code.

License

This project is licensed under the MIT license

More Repositories

1

amethyst

Data-oriented and data-driven game engine written in Rust
Rust
7,982
star
2

specs

Specs - Parallel ECS
Rust
2,483
star
3

legion

High performance Rust ECS library
Rust
1,616
star
4

bracket-lib

The Roguelike Toolkit (RLTK), implemented for Rust.
Rust
1,500
star
5

rustrogueliketutorial

Roguelike Tutorial in Rust - using RLTK
Rust
894
star
6

rendy

State of the art "build your own engine" kit powered by gfx-hal
Rust
815
star
7

distill

Asset pipeline system for game engines & editor suites.
Rust
367
star
8

shred

Shared resource dispatcher
Rust
231
star
9

evoli

An ecosystem-simulation game made with Amethyst
Rust
217
star
10

amethyst-starter-2d

Seed project for 2D games
Rust
201
star
11

space-menace

An action 2D platformer made with Amethyst game engine
Rust
180
star
12

shotcaller

A moddable RTS/MOBA game made with bracket-lib and minigene.
Rust
143
star
13

serde-diff

Utility for comparing two structs and re-applying the differences to other structs
Rust
120
star
14

hibitset

Hierarchical bit set container
Rust
114
star
15

voxel-mapper

Make beautiful voxel maps.
Rust
113
star
16

specs-physics

nphysics integration for the Specs entity component system
Rust
94
star
17

sheep

Modular and lightweight spritesheet packer 🐑
Rust
89
star
18

tools

Game development tools for the Amethyst engine
Rust
80
star
19

grumpy_visitors

🧙‍♂️🧙‍♀️ A prototype of a top-down EvilInvasion-like 2D arcade/action (with co-op!)
Rust
77
star
20

amethyst-imgui

imgui integration for Amethyst
Rust
66
star
21

legion_transform

A Unity-inspired hierarchical transform implementation using Legion ECS
Rust
51
star
22

editor-core

Crate that allows an Amethyst game to communicate with an editor.
Rust
44
star
23

rfcs

RFCs are documents that contain major plans and decisions for the engine
32
star
24

dwarf_seeks_fortune

A 2D puzzle platformer made with the Amethyst game engine.
Rust
25
star
25

amethyst_iced

Iced rendering plugin for the Amethyst game engine
Rust
24
star
26

pong_wasm

WASM end-to-end proof of concept -- work in progress
Rust
22
star
27

web_worker

Rust
19
star
28

ludumdare42

A game made by the Amethyst team for Ludum Dare 42
Rust
16
star
29

website-legacy

Project website and blog (DEPRECATED)
HTML
11
star
30

website

Official Amethyst website
JavaScript
9
star
31

amethyst-rhusics

A bridge between Amethyst and rhusics (unmaintained)
Rust
9
star
32

awesome-specs

A curated list of projects that use or help with using Specs.
6
star
33

crystal-editor

Svelte
6
star
34

ludumdare43

Rust
2
star
35

resources

Files that are important to keep around but not tied to any specific code base
1
star
36

builder

The docker container used in amethyst's CI/CD infrastructure.
Dockerfile
1
star
37

wasm_rush_report

Report about adding WASM support to the Amethyst game engine.
1
star
38

laminar-ffi

Crate that exposes Laminar functionality to C
Rust
1
star
39

amethyst-docs-builder

Webhook server that builds amethyst's book and documentation
Go
1
star
40

amethystup

Setup script for Amethyst dependencies
Shell
1
star
41

documentation

Non-rustdoc documentation and policies
1
star