fix(appimage): build AppRun with bounded argument splitting (#16330)

* fix(appimage): build AppRun with bounded argument splitting

AppRun v2.0.0, which appimage-builder downloads, copies each argument
into a 1 KiB stack buffer in apprun_shell_split_arguments, so any
argument of 1024 bytes or more aborts the AppImage with "buffer overflow
detected" before RustDesk starts (e.g. --connect with a 10000-char id).

Build AppRun from the v2.0.0 commit with a patch that sizes the buffer
from the input and stops the quote/escape scanning at the terminating
NUL, in ubuntu:16.04 like upstream's release, and put it where
appimage-builder looks before downloading.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(appimage): verify the patched AppRun is the one shipped

Reset the split buffer by its first byte rather than zeroing all of it
per argument, check the AppRun source tarball's sha256, pin the build
image by digest, and fail the job if appimage-builder deployed anything
other than the binary built here.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
RustDeskandClaude Opus 5.5 authored and GitHub committed 2026-09-25 00:49:00 +08:00
1 parent efec124c52
commit 483cc10266
3 files changed
+95

No files matched your search

+2
View File
@@ -2444,7 +2444,9 @@ jobs:
sudo pip3 install git+https://github.com/rustdesk-org/appimage-builder.git
# run appimage-builder
pushd appimage
./build-apprun.sh ${{ matrix.job.arch }}
sudo appimage-builder --skip-tests --recipe ./AppImageBuilder-${{ matrix.job.arch }}.yml
cmp AppDir/AppRun appimage-build/AppRun/v2.0.0/AppRun-Release-${{ matrix.job.arch }}
- name: Publish appimage package
if: env.UPLOAD_ARTIFACT == 'true'
+55
View File
@@ -0,0 +1,55 @@
--- a/src/common/shell_utils.c
+++ b/src/common/shell_utils.c
@@ -201,7 +201,8 @@
const char *begin = str;
const char *end = str;
- char buffer[1024] = {0x0};
+ size_t buffer_size = strlen(str) + 1;
+ char *buffer = calloc(buffer_size, sizeof(char));
while (*begin != '\0') {
begin = apprun_string_consume_spaces(begin);
@@ -209,7 +210,7 @@
if (*begin == '\\') {
strncat(buffer, begin + 1, 1);
- end = begin + 2;
+ end = begin[1] != '\0' ? begin + 2 : begin + 1;
consumed = true;
}
@@ -218,7 +219,8 @@
strncat(buffer, begin + 1, end - begin - 1);
consumed = true;
- end++;
+ if (*end != '\0')
+ end++;
}
if (!consumed && *begin == '\"') {
@@ -226,7 +228,8 @@
strncat(buffer, begin + 1, end - begin - 1);
consumed = true;
- end++;
+ if (*end != '\0')
+ end++;
}
if (!consumed && *begin != '\'' && *begin != '\"' && *begin != '\\') {
@@ -240,11 +243,12 @@
split_count++;
}
- memset(buffer, 0, 1024);
+ buffer[0] = '\0';
}
begin = end;
}
+ free(buffer);
return splits;
}
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# AppRun v2.0.0, which appimage-builder downloads, splits every argument into a 1 KiB stack
# buffer, so any argument of 1024 bytes or more aborts the AppImage before RustDesk starts.
# Build it with apprun-split-arguments.patch into the path appimage-builder checks before
# downloading. ubuntu:16.04 is what upstream released from, so the host glibc floor is unchanged.
set -euo pipefail
arch=$1
version=v2.0.0
commit=407700ccef58e1a64cc49856074aee4b1c75d599
sha256=05729f2ae0a744369d2d19d0f37acfbdcb1ee064172955b7576883ccef5113b3
image=ubuntu:16.04@sha256:1f1a2d56de1d604801a9671f301190704c25d604a416f59e03c04f5c6ffee0d6
here=$(cd "$(dirname "$0")" && pwd)
case $arch in
x86_64) packages="cmake make g++" ;;
aarch64) packages="cmake make g++ g++-aarch64-linux-gnu" ;;
*) echo "Unsupported arch: $arch" >&2; exit 1 ;;
esac
tmp=$(mktemp -d)
src=$tmp/src
curl -fsSL -o "$tmp/apprun.tar.gz" "https://github.com/AppImageCrafters/AppRun/archive/$commit.tar.gz"
echo "$sha256 $tmp/apprun.tar.gz" | sha256sum -c -
mkdir "$src"
tar -xzf "$tmp/apprun.tar.gz" -C "$src" --strip-components=1
patch -d "$src" -p1 < "$here/apprun-split-arguments.patch"
docker run --rm -v "$src:/src" -w /src -e DEBIAN_FRONTEND=noninteractive "$image" bash -c "
set -e
apt-get update
apt-get install -y --no-install-recommends $packages
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/$arch-toolchain.cmake
cmake --build . --target AppRun"
mkdir -p "$here/appimage-build/AppRun/$version"
cp "$src/build/src/apprun/AppRun" "$here/appimage-build/AppRun/$version/AppRun-Release-$arch"