diff --git a/go.mod b/go.mod index 190b4cd09..0bdddfc79 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/valyala/fastrand v1.0.0 github.com/valyala/gozstd v1.7.0 github.com/valyala/histogram v1.0.1 - github.com/valyala/quicktemplate v1.5.0 + github.com/valyala/quicktemplate v1.5.1 go.opencensus.io v0.22.4 // indirect golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index ca60ab413..8c0125e9f 100644 --- a/go.sum +++ b/go.sum @@ -171,8 +171,8 @@ github.com/valyala/gozstd v1.7.0 h1:Ljh5c9zboqLhwTI33al32R72iCZfn0mCbVGcFWbGwRQ= github.com/valyala/gozstd v1.7.0/go.mod h1:y5Ew47GLlP37EkTB+B4s7r6A5rdaeB7ftbl9zoYiIPQ= github.com/valyala/histogram v1.0.1 h1:FzA7n2Tz/wKRMejgu3PV1vw3htAklTjjuoI6z3d4KDg= github.com/valyala/histogram v1.0.1/go.mod h1:lQy0xA4wUz2+IUnf97SivorsJIp8FxsnRd6x25q7Mto= -github.com/valyala/quicktemplate v1.5.0 h1:2CUbkvZbxZ9m51wp5a2vzrbnv38Iocp0bMJomSmHyg0= -github.com/valyala/quicktemplate v1.5.0/go.mod h1:v7yYWpBEiutDyNfVaph6oC/yKwejzVyTX/2cwwHxyok= +github.com/valyala/quicktemplate v1.5.1 h1:JtrOtlRMP+pySF9dkPBfVfhZ3YHTitAJpMLNqT9ZjFk= +github.com/valyala/quicktemplate v1.5.1/go.mod h1:v7yYWpBEiutDyNfVaph6oC/yKwejzVyTX/2cwwHxyok= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/vendor/github.com/valyala/quicktemplate/jsonstring.go b/vendor/github.com/valyala/quicktemplate/jsonstring.go index dac862c8a..9154770da 100644 --- a/vendor/github.com/valyala/quicktemplate/jsonstring.go +++ b/vendor/github.com/valyala/quicktemplate/jsonstring.go @@ -1,93 +1,65 @@ package quicktemplate import ( - "io" + "fmt" "strings" ) -func writeJSONString(w io.Writer, s string) { - if len(s) > 24 && - strings.IndexByte(s, '"') < 0 && - strings.IndexByte(s, '\\') < 0 && - strings.IndexByte(s, '\n') < 0 && - strings.IndexByte(s, '\r') < 0 && - strings.IndexByte(s, '\t') < 0 && - strings.IndexByte(s, '\f') < 0 && - strings.IndexByte(s, '\b') < 0 && - strings.IndexByte(s, '<') < 0 && - strings.IndexByte(s, '\'') < 0 && - strings.IndexByte(s, 0) < 0 { - - // fast path - nothing to escape - w.Write(unsafeStrToBytes(s)) - return +func hasSpecialChars(s string) bool { + if strings.IndexByte(s, '"') >= 0 || strings.IndexByte(s, '\\') >= 0 || strings.IndexByte(s, '<') >= 0 || strings.IndexByte(s, '\'') >= 0 { + return true } - - // slow path - write := w.Write - b := unsafeStrToBytes(s) - j := 0 - n := len(b) - if n > 0 { - // Hint the compiler to remove bounds checks in the loop below. - _ = b[n-1] - } - for i := 0; i < n; i++ { - switch b[i] { - case '"': - write(b[j:i]) - write(strBackslashQuote) - j = i + 1 - case '\\': - write(b[j:i]) - write(strBackslashBackslash) - j = i + 1 - case '\n': - write(b[j:i]) - write(strBackslashN) - j = i + 1 - case '\r': - write(b[j:i]) - write(strBackslashR) - j = i + 1 - case '\t': - write(b[j:i]) - write(strBackslashT) - j = i + 1 - case '\f': - write(b[j:i]) - write(strBackslashF) - j = i + 1 - case '\b': - write(b[j:i]) - write(strBackslashB) - j = i + 1 - case '<': - write(b[j:i]) - write(strBackslashLT) - j = i + 1 - case '\'': - write(b[j:i]) - write(strBackslashQ) - j = i + 1 - case 0: - write(b[j:i]) - write(strBackslashZero) - j = i + 1 + for i := 0; i < len(s); i++ { + if s[i] < 0x20 { + return true } } - write(b[j:]) + return false } -var ( - strBackslashQuote = []byte(`\"`) - strBackslashBackslash = []byte(`\\`) - strBackslashN = []byte(`\n`) - strBackslashR = []byte(`\r`) - strBackslashT = []byte(`\t`) - strBackslashF = []byte(`\u000c`) - strBackslashB = []byte(`\u0008`) - strBackslashLT = []byte(`\u003c`) - strBackslashQ = []byte(`\u0027`) - strBackslashZero = []byte(`\u0000`) -) +func appendJSONString(dst []byte, s string, addQuotes bool) []byte { + if !hasSpecialChars(s) { + // Fast path - nothing to escape. + if !addQuotes { + return append(dst, s...) + } + dst = append(dst, '"') + dst = append(dst, s...) + dst = append(dst, '"') + return dst + } + + // Slow path - there are chars to escape. + if addQuotes { + dst = append(dst, '"') + } + bb := AcquireByteBuffer() + var tmp []byte + tmp, bb.B = bb.B, dst + _, err := jsonReplacer.WriteString(bb, s) + if err != nil { + panic(fmt.Errorf("BUG: unexpected error returned from jsonReplacer.WriteString: %s", err)) + } + dst, bb.B = bb.B, tmp + ReleaseByteBuffer(bb) + if addQuotes { + dst = append(dst, '"') + } + return dst +} + +var jsonReplacer = strings.NewReplacer(func() []string { + a := []string{ + "\n", `\n`, + "\r", `\r`, + "\t", `\t`, + "\"", `\"`, + "\\", `\\`, + "<", `\u003c`, + "'", `\u0027`, + } + for i := 0; i < 0x20; i++ { + a = append(a, string([]byte{byte(i)}), fmt.Sprintf(`\u%04x`, i)) + } + return a +}()...) diff --git a/vendor/github.com/valyala/quicktemplate/writer.go b/vendor/github.com/valyala/quicktemplate/writer.go index f913cc817..027d2690d 100644 --- a/vendor/github.com/valyala/quicktemplate/writer.go +++ b/vendor/github.com/valyala/quicktemplate/writer.go @@ -151,9 +151,13 @@ func (w *QWriter) FPrec(f float64, prec int) { // Q writes quoted json-safe s to w. func (w *QWriter) Q(s string) { - w.Write(strQuote) - writeJSONString(w, s) - w.Write(strQuote) + bb, ok := w.w.(*ByteBuffer) + if ok { + bb.B = appendJSONString(bb.B, s, true) + } else { + w.b = appendJSONString(w.b[:0], s, true) + w.Write(w.b) + } } var strQuote = []byte(`"`) @@ -167,7 +171,13 @@ func (w *QWriter) QZ(z []byte) { // // Unlike Q it doesn't qoute resulting s. func (w *QWriter) J(s string) { - writeJSONString(w, s) + bb, ok := w.w.(*ByteBuffer) + if ok { + bb.B = appendJSONString(bb.B, s, false) + } else { + w.b = appendJSONString(w.b[:0], s, false) + w.Write(w.b) + } } // JZ writes json-safe z to w. diff --git a/vendor/modules.txt b/vendor/modules.txt index 08d50ece8..18234d8a9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -108,7 +108,7 @@ github.com/valyala/fastrand github.com/valyala/gozstd # github.com/valyala/histogram v1.0.1 github.com/valyala/histogram -# github.com/valyala/quicktemplate v1.5.0 +# github.com/valyala/quicktemplate v1.5.1 github.com/valyala/quicktemplate # go.opencensus.io v0.22.4 go.opencensus.io