EscapeText now escapes 0xFFFD returned from DecodeRune as 0xFFFD, rather than passing through the original byte.
Fixes #5880.
R=golang-dev, r, bradfitz, adg
CC=golang-dev
https://golang.org/cl/
11975043
 
                case '\r':
                        esc = esc_cr
                default:
-                       if !isInCharacterRange(r) {
+                       if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
                                esc = esc_fffd
                                break
                        }
 
        "reflect"
        "strings"
        "testing"
+       "unicode/utf8"
 )
 
 const testInput = `
                t.Errorf("have %v, want %v", text, expected)
        }
 }
+
+func TestIssue5880(t *testing.T) {
+       type T []byte
+       data, err := Marshal(T{192, 168, 0, 1})
+       if err != nil {
+               t.Errorf("Marshal error: %v", err)
+       }
+       if !utf8.Valid(data) {
+               t.Errorf("Marshal generated invalid UTF-8: %x", data)
+       }
+}