Add lua_eval command, lua IPC command, and scroll.context_container API#347
Open
jbms wants to merge 5 commits into
Open
Add lua_eval command, lua IPC command, and scroll.context_container API#347jbms wants to merge 5 commits into
jbms wants to merge 5 commits into
Conversation
5850d90 to
1761821
Compare
During workspace switch animations, references to the source and target
workspaces (data->from and data->to) are tracked. If a workspace is destroyed
while the animation is active (e.g., when it is emptied or its output is
unplugged), these references become dangling. Upon completion or cancellation of
the animation, accessing the workspaces triggers a use-after-free crash.
To address this, we avoid starting the switch animation if either the
source or target workspace is already marked for destruction (which is
when they can be freed).
Here is a minimal shell script to reproduce the crash on a build without this fix:
```bash
#!/bin/bash
set -x
# Setup isolated run environment
TEMP_DIR=$(mktemp -d)
export XDG_RUNTIME_DIR="$TEMP_DIR"
export WLR_BACKENDS=headless
export WLR_LIBINPUT_NO_DEVICES=1
export LSAN_OPTIONS=detect_leaks=0
unset DISPLAY
unset WAYLAND_DISPLAY
# Create minimal configuration
cat <<EOF > "$TEMP_DIR/config"
animations enabled on
EOF
# Start scroll compositor headlessly
./build/sway/scroll -c "$TEMP_DIR/config" -d > "$TEMP_DIR/scroll.log" 2>&1 &
SCROLL_PID=$!
# Wait for the compositor to start up and open its wayland socket
for i in {1..50}; do
SOCKET_PATH=$(find "$XDG_RUNTIME_DIR" -name "wayland-*" | head -n 1)
if [ -n "$SOCKET_PATH" ] && [ -S "$SOCKET_PATH" ]; then
break
fi
sleep 0.1
done
if [ -z "$SOCKET_PATH" ] || [ ! -S "$SOCKET_PATH" ]; then
echo "Error: scroll failed to start or open socket"
cat "$TEMP_DIR/scroll.log"
kill $SCROLL_PID || true
rm -rf "$TEMP_DIR"
exit 1
fi
SOCKET_NAME=$(basename "$SOCKET_PATH")
# Switch to workspace 2 and immediately switch back to workspace 1 to trigger UAF
export SWAYSOCK="$XDG_RUNTIME_DIR/i3-ipc.sock"
if [ ! -S "$SWAYSOCK" ]; then
# Look for the IPC socket
SWAYSOCK=$(find "$XDG_RUNTIME_DIR" -name "*.sock" | head -n 1)
fi
echo "Using SWAYSOCK=$SWAYSOCK"
./build/swaymsg/scrollmsg -s "$SWAYSOCK" "workspace 2; workspace 1" 2>&1
# Wait a brief moment for the crash to complete and the process to terminate
sleep 0.5
# Check if the compositor crashed
if kill -0 $SCROLL_PID 2>/dev/null; then
echo "Compositor is still running! Reproduction FAILED."
echo "=== COMPOSITOR LOG ==="
cat "$TEMP_DIR/scroll.log"
kill $SCROLL_PID
rm -rf "$TEMP_DIR"
exit 1
else
echo "Compositor has terminated (expected)!"
cat "$TEMP_DIR/scroll.log"
rm -rf "$TEMP_DIR"
exit 0
fi
```
Exposes scroll.animating() and scroll.pending_transactions() to Lua to allow external scripts and tests to query whether the compositor has settled. Also includes testing infrastructure updates (pytest.ini config, LSan suppressions, and helper methods in test_utils.py).
Add a new `lua_eval` compositor command to allow executing a raw inline Lua string as code rather than loading a file. Any optional arguments passed are supplied to the inline Lua block as parameters (accessed via `...`). The empty string is used as the script identifier. Also update the `scroll` manual page and README.md to document the new command.
Add a new `lua` IPC command type (represented by `IPC_LUA_EXEC` = 124) to support evaluating either a Lua script file or inline Lua code. The message accepts arguments as a list of JSON values which are parsed and converted to Lua values, and serializes the return value(s) of the script back to JSON before replying. In the `scrollmsg` client, expose this through separate `lua` (for running a file) and `lua_eval` (for running inline code) command types. Also: - Export and reuse `sway_lua_value_to_json` and `sway_lua_table_to_json` from `sway/lua.c` for Lua-to-JSON serialization in the IPC reply. - Export `sway_lua_push_json_to_lua` for JSON-to-Lua argument conversion. - Fix relative stack index handling in JSON/Lua conversion functions to ensure they function correctly with negative stack indices. - Commit dirty transactions immediately after the script execution on both success and error execution paths. - Rewrite the `execute_lua` test helper to use the new IPC API directly (removing temporary files and the custom Lua runner). - Update man pages (scrollmsg.1, scroll-ipc.7) and README.md.
Exposes the criteria-matched container context to running Lua scripts via a new `scroll.context_container()` function. If a script is run via criteria (e.g., `[class="XTerm"] lua_eval ...`), the function returns the matched container's ID. If executed globally without criteria, it returns `nil`. To prevent nested executions of `scroll.command()` within a script from permanently overwriting the context, the active Lua context is backed up on entry to Lua command handlers (`lua` and `lua_eval`) and restored on exit. Also documents the new API in `scroll.lua` and the `scroll.5` man page, and adds comprehensive pytest coverage.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
lua_evalallows inline lua to be evaluated without needing to write it to a file.Compared to just running
luaorlua_evalvia RUN_COMMAND, the new LUA_EXEC command allows a return value to be sent back to the client.The scroll.context_container() API provides access to the context container when
luaorlua_evalis run with criteria.