Watch
0
0
Fork
You've already forked hyperhive
0

fix(forge): pass avatar image via files, not argv (E2BIG over 128 KiB)

forge-avatar-sync passed the base64-encoded icon as a jq --arg and then
as a curl -d command-line argument. Linux caps a single exec argument at
MAX_ARG_STRLEN (128 KiB), so any icon whose rasterized PNG base64-encodes
past that (red's does, at 133300 bytes) makes jq fail with E2BIG before
curl is ever reached, and the avatar upload silently never happens. The
base64 and the JSON payload now go through temp files instead of argv.

Closes #4839
This commit is contained in:
atlas 2026-09-30 19:17:59 +02:00
commit b0d92ccbd8

View file

@ -246,16 +246,22 @@ in
exit 0
fi
TOKEN=$(cat "$TOKEN_FILE")
IMAGE=$(base64 -w 0 < ${iconPng})
# The base64'd icon can exceed Linux's MAX_ARG_STRLEN (128 KiB
# per exec argument), so it must never be passed on a command
# line — not to jq as --arg, not to curl as -d. Route it through
# files instead.
IMAGE_FILE=$(mktemp)
PAYLOAD_FILE=$(mktemp)
trap 'rm -f "$IMAGE_FILE" "$PAYLOAD_FILE"' EXIT
base64 -w 0 < ${iconPng} > "$IMAGE_FILE"
# Forgejo POST /user/avatar expects {"image":"<base64>"} — just the
# raw base64 string, NOT a data URI (data:image/png;base64,...).
# Use jq to build the payload so the large base64 value is safely quoted.
PAYLOAD=$(jq -n --arg img "$IMAGE" '{image:$img}')
jq -n --rawfile img "$IMAGE_FILE" '{image:($img|rtrimstr("\n"))}' > "$PAYLOAD_FILE"
RESP=$(curl -sf --max-time 10 \
-X POST "$FORGE_URL/api/v1/user/avatar" \
-H "Authorization: token $TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
--data-binary @"$PAYLOAD_FILE" \
-w "\n%{http_code}" 2>/dev/null || true)
CODE=$(printf '%s' "$RESP" | tail -1)
if [ "$CODE" = "204" ] || [ "$CODE" = "200" ]; then