Address review findings on the VNC server, session auth and capture decoder

This commit is contained in:
Viktor Liu
2026-08-27 18:33:52 +02:00
parent 09e069a175
commit 47d8f912e5
18 changed files with 179 additions and 72 deletions
+19 -2
View File
@@ -7,6 +7,7 @@ import (
"fmt"
"io"
"time"
"unicode/utf8"
)
// clipboardPoll periodically checks the server-side clipboard and sends
@@ -192,8 +193,10 @@ func (s *session) handleExtClipProvide(flags uint32, payload []byte) {
// host clipboard contents, capped to extClipMaxText.
func (s *session) sendExtClipProvideText() error {
text := s.injector.GetClipboard()
if len(text) > extClipMaxText {
text = text[:extClipMaxText]
// One byte short of the cap: buildExtClipProvideText appends a NUL
// terminator, which counts against extClipMaxText.
if len(text) > extClipMaxText-1 {
text = trimPartialRune(text[:extClipMaxText-1])
}
payload, err := buildExtClipProvideText(text)
if err != nil {
@@ -202,6 +205,20 @@ func (s *session) sendExtClipProvideText() error {
return s.writeExtClipMessage(payload)
}
// trimPartialRune drops the trailing bytes a byte-length cut left halfway
// through a UTF-8 rune, so the client is never handed invalid UTF-8. A real
// U+FFFD in the text decodes as three bytes and is kept.
func trimPartialRune(s string) string {
for s != "" {
r, size := utf8.DecodeLastRuneInString(s)
if r != utf8.RuneError || size > 1 {
return s
}
s = s[:len(s)-1]
}
return s
}
// writeExtClipMessage frames an ExtendedClipboard payload as a ServerCutText
// message with a negative length, then writes it under writeMu.
func (s *session) writeExtClipMessage(payload []byte) error {