Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
adfd4b2
add official lua test suite
levno-710 Oct 27, 2026
356cd84
remove redundant README notes
levno-710 Oct 27, 2026
e389f84
fix number serialization
levno-710 Oct 27, 2026
b5cf7f3
preserve non-finite values during number mutation
levno-710 Oct 27, 2026
67e3fd8
preserve nil argument and return counts in vmify
levno-710 Oct 27, 2026
47452ab
fix nested function declaration dependencies in vmify
levno-710 Oct 27, 2026
493f3ea
preserve single-value semantics for parenthesized expressions
levno-710 Oct 27, 2026
a39dc3a
preserve method lookup ordering in vmify
levno-710 Oct 27, 2026
08af2d0
prevent overflow in hexadecimal number mutation
levno-710 Oct 27, 2026
feee70b
release dead vm references after their final use
levno-710 Oct 27, 2026
78cb5c1
limit merged vm assignments to the temporary register budget
levno-710 Oct 27, 2026
9913a6b
drop legacy arg compatibility from upstream tests
levno-710 Oct 27, 2026
db8801d
exclude running environment changes from upstream tests
levno-710 Oct 27, 2026
9c4c9f8
fix numeric for loop coercion in vmify
levno-710 Oct 27, 2026
ee9fa6d
preserve all generic for iterator results in vmify
levno-710 Oct 27, 2026
225e0b0
preserve indexed assignment targets in vmify
levno-710 Oct 27, 2026
e34bc1b
honor function environments in vmify
levno-710 Oct 27, 2026
3ba0fdd
extend limitation docs
levno-710 Oct 27, 2026
ad98af4
fix vm dispatch for consecutive block ids
levno-710 Oct 27, 2026
20d547c
prevent block ids from overwriting dispatch entries
levno-710 Oct 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ Dockerfile
.dockerignore
.git
.gitignore

test-results
__pycache__
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
*.lua text=auto
*.lua eol=lf

# Preserve the official archive byte-for-byte for checksum verification.
tests/upstream/lua51/vendor/** -text !eol
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ web/playwright-report
test.lua
test.obfuscated.lua
config.lua

# Lua test logs and reproduction artifacts
/test-results/
__pycache__/
11 changes: 10 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ FROM ubuntu:24.04

RUN apt-get update && apt-get install -y \
lua5.1 \
python3 \
patch \
git \
unzip \
curl \
&& rm -rf /var/lib/apt/lists/*

# Download pre-built Luau binary
RUN curl -sSLo /tmp/luau-ubuntu.zip \
RUN --mount=type=secret,id=ca-bundle \
if [ -f /run/secrets/ca-bundle ]; then export CURL_CA_BUNDLE=/run/secrets/ca-bundle; fi; \
curl -fsSLo /tmp/luau-ubuntu.zip \
https://github.com/luau-lang/luau/releases/latest/download/luau-ubuntu.zip \
&& unzip -j /tmp/luau-ubuntu.zip luau -d /usr/local/bin \
&& chmod +x /usr/local/bin/luau \
Expand All @@ -20,4 +24,9 @@ RUN lua5.1 -v && printf 'print("luau OK")\n' > /tmp/luau_check.lua && luau /tmp/
WORKDIR /app
COPY . /app

RUN lua5.1 tests/harness/metadata.lua \
&& timeout 30s lua5.1 tests/harness/numbers-to-expressions.lua \
&& timeout 30s lua5.1 tests/harness/vm-arity.lua \
&& python3 tests/harness/runner.py

ENTRYPOINT ["lua5.1", "docker-test-runner.lua"]
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ Currently, Prometheus supports:
- **Lua 5.1**
- **LuaU** *(basic support is available, but still not fully finished)*

Lua 5.1's legacy implicit `arg` table in vararg functions is unsupported.
Use `...` and `select('#', ...)` instead; see [Limitations](doc/reference/limitations.md).
Replacing a function's environment while it is running is also unsupported;
set the environment before calling the function.

---


Expand Down Expand Up @@ -138,14 +143,17 @@ For more advanced use cases, configuration, and presets, see the [documentation]

## Tests

The test suite runs inside Docker with lua5.1 and Luau:
The test suite runs existing cases on Lua 5.1 and Luau, plus the adapted
official Lua 5.1 suite on Lua 5.1, inside Docker:

```bash
./scripts/run-tests.sh # Run all tests (default: 10 iterations)
./scripts/run-tests.sh -b # Build image and run tests
./scripts/run-tests.sh -n 5 # Run with 5 iterations
./scripts/run-tests.sh -c config.lua # Use a custom config
./scripts/run-tests.sh -v # Verbose output
./scripts/run-tests.sh --suite upstream --baseline-only # Verify official originals
./scripts/run-tests.sh --case lua51/closure.lua --preset Vmify --seed 4 -n 1
```

---
Expand Down
1 change: 1 addition & 0 deletions doc/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

## Reference

* [Limitations](reference/limitations.md)
* [CLI Options Reference](reference/cli-options.md)
* [Config Object Reference](reference/config-object.md)
* [Step Pipeline Overview](reference/steps/overview.md)
Expand Down
104 changes: 104 additions & 0 deletions doc/reference/limitations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Limitations

Scripts that rely on the following behavior may require changes before
obfuscation:

- Replacing a function's environment while it is running, including `module(...)`.
- Lua 5.1's legacy implicit `arg` variable in vararg functions.
- Debug access to original functions, locals, upvalues, source locations, or call stacks.
- Debug hooks or debug-based changes to coroutine environments or primitive metatables.
- Exact tail-call capacity, memory usage, collection timing, or runtime limits.
- Inspection of original bytecode or native runtime layout.

Source code constructed or loaded at runtime is not automatically obfuscated.

## Replacing a running function's environment

Prometheus does not support replacing a function's environment while that
function is running. This includes `setfenv(1, env)`, changing an active
caller with `setfenv(2, env)`, and `setfenv(f, env)` when `f` is currently
executing. Subsequent global reads and writes may still use the environment
from the start of the call.

Lua 5.1's `module(...)` also replaces the calling function's environment,
so calling it from transformed code is subject to the same limitation.
Use explicit module tables instead.

Setting a function's environment before calling it is supported:

```lua
setfenv(f, env)
f()
```

This limitation concerns replacing a running function's environment, not
mutating values in an environment table or changing the thread's default
environment with `setfenv(0, env)`.

## Legacy implicit `arg` table

Prometheus does not support Lua 5.1's legacy compatibility behavior that creates
an implicit local `arg` table in vararg functions, or an implicit nil `arg`
when the function uses `...` in its body. Minification may preserve this
behavior on a compatible host runtime, but obfuscation does not guarantee it.

Use explicit varargs instead:

```lua
local function pack(...)
return {n = select('#', ...), ...}
end
```

The explicit `n` preserves the argument count even when arguments contain nils.
Ordinary explicit locals named `arg` and the CLI's global argument table are
unaffected by this limitation.

## Debug introspection and mutation

Obfuscation changes functions, locals, upvalues, source text, and call stacks.
Compatibility with the original program's debug representation is unsupported.
In particular, do not rely on:

- `debug.getinfo` returning original source names, function names, or line numbers.
- Debug local and upvalue access or mutation referring to the original variables,
including after a function is dumped and loaded.
- Tracebacks preserving original stack frames, formatting, or error locations.
- Debug hooks observing the original call, return, line, or instruction sequence.
- `debug.getfenv` or `debug.setfenv` accessing coroutine environments as in the
original script.
- `debug.setmetatable` changing the behavior of primitive types such as numbers,
booleans, and nil.

Ordinary table and userdata metatables are supported.

## Exact runtime limits and garbage-collection behavior

Prometheus does not guarantee that transformed code has the same resource
usage, implementation limits, or collection schedule as the original code.
Do not rely on identical:

- Tail-call or method-tail-call stack capacity. Deep tail recursion may exhaust
the stack after obfuscation.
- String-size and allocation limits, memory usage, or execution timing.
- Parser nesting, local-variable or upvalue limits, or exact diagnostic text.
- Garbage-collector allocation thresholds, step sizes, or step counts.
- Userdata lifetime, finalization order, or the timing of weak-table removal.
- Finalizer resurrection and error behavior during collection or interpreter shutdown.

`collectgarbage`, weak tables, and userdata finalizers are not generally
unsupported, but scripts should not depend on their exact scheduling.

## Bytecode and native runtime layout

Obfuscation does not preserve the original bytecode, instructions, function
layout, or table allocation layout. Scripts or native extensions that inspect
these details cannot assume they match the original program. Dumping a
transformed function produces its transformed representation.

## Code loaded at runtime

Prometheus transforms the source files supplied to it. Source strings or files
loaded later through `loadstring`, `load`, `loadfile`, or `require` execute
through the host interpreter and are not automatically transformed. Obfuscate
those files separately if they also need protection.
Loading
Loading