fix(appimage): cd "$APPDIR" in AppRun before exec to fix sharun preload CWD resolution (#2829)

Co-authored-by: Taimoor <astikkosapparel009@gmail.com>
Co-authored-by: sanil-23 <sanil@vezures.xyz>
This commit is contained in:
Shaikh Taimoor
2026-05-29 00:33:26 +05:30
committed by GitHub
co-authored by Taimoor sanil-23
parent 38238d63d5
commit 97e4854ccb
@@ -363,6 +363,80 @@ validate_sharun_lib_path() {
fi
}
# patch_apprun_sharun_cwd — inject `cd "$APPDIR"` into AppRun before the final
# exec call so sharun resolves preload/library paths relative to the AppDir
# rather than the caller's CWD.
#
# Problem (issue #2822): sharun reads its `.preload` entry and library search
# paths relative to the process CWD. When a user launches the AppImage from
# any directory other than the AppDir itself (e.g. double-click from ~/Downloads)
# CWD != AppDir, so ld.so can't find `anylinux.so` (preload) or `libcef.so`
# (LD_LIBRARY_PATH entry). SHARUN_DIR is set correctly — the AppDir IS known —
# but sharun doesn't use it to anchor the preload/library arguments it hands to
# ld.so.
#
# Fix: prepend `cd "$APPDIR"` to the exec line in AppRun so the working
# directory is always the AppDir by the time sharun/the binary runs. This
# mirrors the verified manual workaround from the bug report.
#
# Returns 0 (true) if the AppRun was modified, 1 if no change was needed.
patch_apprun_sharun_cwd() {
local appdir="$1"
if ! uses_sharun_launcher "$appdir"; then
return 1
fi
local apprun="$appdir/AppRun"
if [ ! -f "$apprun" ]; then
# Some sharun bundles use the sharun binary directly as the AppDir entry
# point without a separate shell AppRun. Nothing to patch in that case.
return 1
fi
# Check if the file is a shell script (not an ELF binary).
local first_bytes
first_bytes="$(LC_ALL=C head -c 2 "$apprun" 2>/dev/null || true)"
if [ "$first_bytes" = $'\x7fE' ]; then
# AppRun is an ELF binary — cannot patch with sed.
return 1
fi
# Idempotency guard: skip if we already patched this AppRun.
# Match only the exact patched line — a loose substring (e.g. 'cd.*"$APPDIR"')
# would false-positive on comments like '# cd "$APPDIR"' or unrelated lines
# and leave the real `exec "$@"` unpatched.
local patched_line_re='^[[:space:]]*cd[[:space:]]+"\$APPDIR"[[:space:]]*&&[[:space:]]*exec[[:space:]]+"\$@"[[:space:]]*$'
if grep -Eq "$patched_line_re" "$apprun" 2>/dev/null; then
return 1
fi
# Locate the exec line. AppRun scripts generated by lib4bin / sharun
# typically have a line of the form (possibly with leading whitespace):
# exec "$@"
# Patch it to:
# cd "$APPDIR" && exec "$@"
#
# The sed pattern is anchored to end-of-line ($) so trailing content (extra
# args, comments, redirections) doesn't get silently absorbed into the cd &&
# exec sequence.
#
# Use a temp file + mv to avoid truncating AppRun mid-write on failure.
local tmp_apprun
tmp_apprun="$(mktemp)"
if sed 's|^\([[:space:]]*\)exec "\$@"[[:space:]]*$|\1cd "$APPDIR" \&\& exec "$@"|' \
"$apprun" > "$tmp_apprun" \
&& grep -Eq "$patched_line_re" "$tmp_apprun"; then
chmod --reference="$apprun" "$tmp_apprun"
mv "$tmp_apprun" "$apprun"
echo "[strip-libs] patched AppRun: added 'cd \"\$APPDIR\"' before exec to fix sharun CWD preload resolution (issue #2822)"
return 0
else
rm -f "$tmp_apprun"
echo "[strip-libs] WARNING: could not locate 'exec \"\$@\"' in AppRun — sharun CWD fix not applied; AppImage may fail to launch from non-AppDir CWDs" >&2
return 1
fi
}
strip_one_appimage() {
local img="$1"
local original
@@ -386,6 +460,7 @@ strip_one_appimage() {
local removed=0
local added_loader=0
local rewrote_libpath=0
local patched_apprun=0
local lib_roots=()
for candidate in \
"$appdir/usr/lib" \
@@ -420,14 +495,17 @@ strip_one_appimage() {
if rewrite_sharun_lib_path "$appdir"; then
rewrote_libpath=1
fi
if patch_apprun_sharun_cwd "$appdir"; then
patched_apprun=1
fi
validate_sharun_lib_path "$appdir"
if [ "$removed" -eq 0 ] && [ "$added_loader" -eq 0 ] && [ "$rewrote_libpath" -eq 0 ]; then
if [ "$removed" -eq 0 ] && [ "$added_loader" -eq 0 ] && [ "$rewrote_libpath" -eq 0 ] && [ "$patched_apprun" -eq 0 ]; then
echo "[strip-libs] No graphics libs or missing sharun interpreter found in $original; leaving unchanged."
rm -rf "$workdir"
return
fi
echo "[strip-libs] Removed $removed file(s), added $added_loader loader file(s); repacking AppImage."
echo "[strip-libs] Removed $removed file(s), added $added_loader loader file(s), patched AppRun=$patched_apprun; repacking AppImage."
local rebuilt="$workdir/$name"
local appimage_arch