Commit abe3f5c8 by Iwasaki Yudai

Don't send invalid UTF-8 string

When a rune stands over the buffer boundary, invalid UTF-8 bytes were
sent to the client. Now the logic checks if the tail of the buffer can
be decoded as a valid rune. When it's an invalid byte sequence, the logic
keeps it in the buffer and send it in the next loop with the following byte sequence.
1 parent 31b714be
Showing with 35 additions and 6 deletions
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"syscall" "syscall"
"unicode/utf8"
"unsafe" "unsafe"
"github.com/elazarl/go-bindata-assetfs" "github.com/elazarl/go-bindata-assetfs"
...@@ -53,8 +54,8 @@ func (app *App) generateHandler() func(w http.ResponseWriter, r *http.Request) { ...@@ -53,8 +54,8 @@ func (app *App) generateHandler() func(w http.ResponseWriter, r *http.Request) {
log.Printf("New client connected: %s", r.RemoteAddr) log.Printf("New client connected: %s", r.RemoteAddr)
upgrader := websocket.Upgrader{ upgrader := websocket.Upgrader{
ReadBufferSize: 0, ReadBufferSize: 1024,
WriteBufferSize: 0, WriteBufferSize: 1024,
Subprotocols: []string{"gotty"}, Subprotocols: []string{"gotty"},
} }
...@@ -81,19 +82,47 @@ func (app *App) generateHandler() func(w http.ResponseWriter, r *http.Request) { ...@@ -81,19 +82,47 @@ func (app *App) generateHandler() func(w http.ResponseWriter, r *http.Request) {
go func() { go func() {
defer func() { exit <- true }() defer func() { exit <- true }()
buf := make([]byte, 512) buf := make([]byte, 1024)
leftOver := 0
for { for {
len, err := fio.Read(buf) size, err := fio.Read(buf[leftOver:])
size += leftOver
if err != nil { if err != nil {
log.Printf("command exited for: %s", r.RemoteAddr) log.Printf("command exited for: %s", r.RemoteAddr)
return return
} }
writer, err := conn.NextWriter(1)
writer, err := conn.NextWriter(websocket.TextMessage)
if err != nil { if err != nil {
return return
} }
writer.Write(buf[0:len])
// UTF-8 Boundary check
for leftOver = 0; leftOver < utf8.UTFMax; leftOver++ {
re, _ := utf8.DecodeLastRune(
buf[:size-leftOver],
)
if re != utf8.RuneError {
break
}
// Invalid UTF rune
}
if leftOver == utf8.UTFMax-1 {
re, _ := utf8.DecodeLastRune(buf[:size-leftOver])
if re == utf8.RuneError {
log.Fatal("UTF8 Boundary error.")
}
}
writer.Write(buf[:size-leftOver])
writer.Close() writer.Close()
for i := 0; i < leftOver; i++ {
buf[i] = buf[size-leftOver+i]
}
} }
}() }()
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!