Tags: luau-lang/lute
Tags
stdlib: Update the testing api with some more test lifecycle methods … …+ testing assertions (#411) This PR comes with some changes to the testing api to reduce the amount of global state we depend on - when making subcases, we now pass in the suite object on which the user can operate. Additionally, assertions are passed in with the test case itself, making them more accessible and reducing an additional line of code needed to start writing tests. - [x] {before,after}x{all,each} lifecycle methods - [x] Table assertions For example: <img width="463" height="79" alt="image" src="https://github.com/user-attachments/assets/31003849-ae2c-469d-a23b-415c4135865b" />
fix: reserve stack slot for thread (#432) When running a script with `LUA_MINSTACK - 1` (19) or more arguments, Luau fails with `L->top < L->ci->top`, because `getRefForThread` tries to push the current thread onto a full stack [in `runBytecode`](https://github.com/luau-lang/lute/blob/a70354de11446cc95b65f00d853b0c3d0b0faf84/lute/cli/src/climain.cpp#L115). The stack only had `argc` slots, because it was resized in `setupArguments`. With this PR, `setupArguments` reserves one more slot (an alternative would be to reserve space in `getRefForThread`). `setupArguments` should probably be declared `static` as well, since it's not declared in any header.
refactor: split `cliruntimefixture` into .h and .cpp (#426) continuation of #416 (comment) to avoid duplicating a `static` function each time the header is included --------- Co-authored-by: Varun Saini <61795485+vrn-sn@users.noreply.github.com>
Fix use-after-free bug in `process.cpp` (#421) ### Problem The issue can be replicated with a simple script that calls `process.run` twice, like this: ```luau local process = require("@lute/process") process.run({"echo", "hello!"}) process.run({"echo", "goodbye!"}) ``` Very rarely, some runs throw unexpected errors, crash, or corrupt Lute output with random bytes. The problem is a subtle UAF bug in `process.cpp`. Despite the small PR diff, this was a very tricky bug to nail down. Had to go digging pretty deep into the libuv source to understand what was going on. Essentially, it's not correct to check if the `stdout` and `stderr` pipes are active before closing them. Since these pipes are used as read-only data streams, they're automatically made inactive by libuv upon reaching EOF. In this situation, we don't need to call `uv_read_stop` on these streams because they're already stopped (although it is fine to do it; `uv_read_stop` is [idempotent](https://docs.libuv.org/en/v1.x/stream.html#c.uv_read_stop)), but we do still need to close the underlying pipe handle. We're currently in a situation where calling `process.run` might immediately close either the `stdout` or `stderr` streams (at EOF), causing the `uv_is_active` check to fail, preventing us from calling `uv_close` on the handle and from incrementing `pendingCloses`. Failing to close these handles means that libuv retains data internally associated with them, and by not incrementing `pendingCloses` (essentially a refcount), we end up destroying the owning `ProcessHandle` of these handles before libuv has been able to clean them up internally. Then, when we go to initialize new handles for the next `process.run` call, we have a UAF manifest deep inside of libuv's circular doubly linked queue code: adding a new handle to the data structure requires adjusting pointers on the last-added handle, which happens to be a handle created from the previous `process.run` call. At this point, it is freed memory that was supposed to be removed from libuv's internals before being freed (using `uv_close`). ### Solution Check instead if the handles still need closing with `!uv_is_closing` since `uv_is_active` is not relevant to whether `uv_close` needs to be called in this case.
stdlib: Introduce a small standard library utility for writing tests … …in lute (#393) Based on [frktest](https://github.com/itsfrank/frktest) This testing utility needs a bunch of assertions to be more useful, but this PR just scopes out what a simple, builtin testing api in Luau could look like. For some tests that look like: ``` local test = require("@std/test") local check = test.assert test.case("foo", function() check.eq(3, 3) check.eq(6, 1) end) test.case("bar", function() check.eq("a", "b") end) test.case("baz", function() check.neq("a", "b") end) test.suite("MySuite", function() test.case("subcase", function() check.eq(5 * 5, 3) end) end) test.run(); ``` this will render as: ``` ❯ ./build/xcode/debug/lute/cli/lute run examples/testing.luau ================================================== TEST RESULTS ================================================== Failed Tests (3): ❌ foo ./examples/testing.luau:5 eq: 6 ~= 1 ❌ bar ./examples/testing.luau:10 eq: a ~= b ❌ MySuite.subcase ./examples/testing.luau:20 eq: 25 ~= 3 -------------------------------------------------- Total: 4 Passed: 1 ✓ Failed: 3 ✗ ================================================== ``` Currently reports: - [x] Test suites and cases - [x] Line numbers - [x] Stack traces - [x] The expression that failed.
Update the bootstrap script to actually build two copies of lute (#386) The bootstrap script didn't correctly generate the lute standard library headers that the `luthier` script did. This PR: - generates a minimal header and implementation for the lute standard libraries during the bootstrap phase - uses these headers to build a `bootstrapped-lute` binary - uses that `bootstrapped-lute` to run `luthier.luau` which builds the actual `lute` executable with the `std` library correctly generated. - accepts an `--install` argument to install this `lute` binary to `$HOME/.lute/bin`. There are some additional improvements that have been made: 1. General README fixes 2. This script can now be run multiple times in sequence, and it correctly deletes artifacts generated by the bootstrapping process each time (e.g. generated std headers, dependencies). 3. Uses git commands to `clone` only the particular revision of the `extern` dependencies we care about, not the entire history. --------- Co-authored-by: ariel <aweiss@hey.com>
PreviousNext