go.talks/pkg/socket: sanitize message bodies
This change prevents a socket connection from going down when a program
emits garbage, as the JSON encoder chokes on invalid UTF-8.
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/8589051
diff --git a/pkg/socket/socket.go b/pkg/socket/socket.go
index f58db5e..13c6e8e 100644
--- a/pkg/socket/socket.go
+++ b/pkg/socket/socket.go
@@ -14,6 +14,7 @@
package socket
import (
+ "bytes"
"encoding/json"
"io"
"io/ioutil"
@@ -23,6 +24,7 @@
"path/filepath"
"runtime"
"strconv"
+ "unicode/utf8"
"code.google.com/p/go.net/websocket"
)
@@ -213,10 +215,24 @@
}
func (w *messageWriter) Write(b []byte) (n int, err error) {
- w.out <- &Message{Id: w.id, Kind: w.kind, Body: string(b)}
+ w.out <- &Message{Id: w.id, Kind: w.kind, Body: safeString(b)}
return len(b), nil
}
+// safeString returns b as a valid UTF-8 string.
+func safeString(b []byte) string {
+ if utf8.Valid(b) {
+ return string(b)
+ }
+ var buf bytes.Buffer
+ for len(b) > 0 {
+ r, size := utf8.DecodeRune(b)
+ b = b[size:]
+ buf.WriteRune(r)
+ }
+ return buf.String()
+}
+
// limiter returns a channel that wraps dest. Messages sent to the channel are
// sent to dest. After msgLimit Messages have been passed on, a "kill" Message
// is sent to the kill channel, and only "end" messages are passed.