Skip to content

terminal/kitty: graphics S value is exact byte, not max - #13892

Merged
mitchellh merged 1 commit into
mainfrom
kitty-s
Aug 18, 2026
Merged

mitchellh merged 1 commit into
mainfrom
kitty-s

Conversation

@mitchellh

Copy link
Copy Markdown
Contributor

File transmissions with exactly S bytes or trailing file data previously failed because appendRemaining reports StreamTooLong when it reaches its limit. This broke the protocol's partial-file transmission path.

Use an exact-length allocation and read when S is nonzero, rejecting premature EOF and values above the image limit. Preserve the existing bounded read-to-EOF behavior for S=0.

https://sw.kovidgoyal.net/kitty/graphics-protocol/#local-client

File transmissions with exactly S bytes or trailing file data previously
failed because appendRemaining reports StreamTooLong when it reaches its
limit. This broke the protocol's partial-file transmission path.

Use an exact-length allocation and read when S is nonzero, rejecting
premature EOF and values above the image limit. Preserve the existing
bounded read-to-EOF behavior for S=0.

https://sw.kovidgoyal.net/kitty/graphics-protocol/#local-client
@mitchellh mitchellh added this to the 1.4.0 milestone Aug 18, 2026
@mitchellh
mitchellh requested a review from a team as a code owner August 18, 2026 17:40
@mitchellh

mitchellh commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor Author

Verification:

#!/usr/bin/env bash
set -euo pipefail

# KGP-06: S must select exactly that many bytes from a regular file.
# The file contains a red RGB pixel followed by a green RGB pixel. S=3 means
# the terminal must read only the red pixel; reading all six bytes is invalid
# for the declared 1x1 RGB image.

tty=/dev/tty
data_file="/tmp/kitty-graphics-protocol-kgp06.$$"
image_id=4242006
in_alt_screen=0
exec 3<>"$tty"

cleanup() {
    trap - EXIT HUP INT TERM
    if [ "$in_alt_screen" -eq 1 ]; then
        printf '\033_Ga=d,d=I,i=%s,q=2\033\\' "$image_id" >&3 || true
        printf '\033[?1049l' >&3 || true
    fi
    rm -f "$data_file"
}
trap cleanup EXIT HUP INT TERM

# This is one red RGB pixel followed by one green RGB pixel:
# ff 00 00 00 ff 00.
printf '\377\000\000\000\377\000' >"$data_file"
actual_size=$(wc -c <"$data_file" | tr -d ' ')
if [ "$actual_size" -ne 6 ]; then
    printf 'FAIL: fixture is %s bytes instead of 6\n' "$actual_size" >&2
    exit 1
fi
encoded_path=$(printf '%s' "$data_file" | base64 | tr -d '\r\n')

# Use a known screen position so running at the bottom of a terminal cannot
# immediately scroll the placement away.
printf '\033[?1049h\033[2J\033[H' >"$tty"
in_alt_screen=1
printf 'KGP-06: file contains red + green pixels; S=3 selects red.\n' >&3
printf 'Expected: a solid red 10x3-cell rectangle below.\n' >&3
printf '\033[3;1H' >&3

# Read the response ourselves so it does not end up in the shell input buffer.
printf '\033_Ga=T,f=24,t=f,s=1,v=1,S=3,O=0,i=%s,c=10,r=3,C=1;%s\033\\' \
    "$image_id" "$encoded_path" >&3
response=
while IFS= read -r -s -n 1 -t 10 char <&3; do
    response+="$char"
    if [[ "$response" == *$'\033\\' ]]; then
        break
    fi
done

printf '\033[7;1H' >&3
case "$response" in
    *';OK'*)
        printf 'PASS: terminal accepted exactly S=3 bytes.\n' >&3
        ;;
    '')
        printf 'FAIL: terminal did not send a graphics response.\n' >&3
        ;;
    *)
        printable=$(printf '%s' "$response" | LC_ALL=C tr -cd '\11\12\15\40-\176')
        printf 'FAIL: terminal response: %s\n' "$printable" >&3
        ;;
esac

printf 'Press Enter to remove the image and return to the previous screen...' >&3
IFS= read -r _ <&3

@mitchellh
mitchellh merged commit 364f8e9 into main Aug 18, 2026
195 checks passed
@mitchellh
mitchellh deleted the kitty-s branch August 18, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant