Initial commit
This commit is contained in:
15
vendor/github.com/cockroachdb/redact/.gitignore
generated
vendored
Normal file
15
vendor/github.com/cockroachdb/redact/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
7
vendor/github.com/cockroachdb/redact/.travis.yml
generated
vendored
Normal file
7
vendor/github.com/cockroachdb/redact/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.12.x
|
||||
- 1.13.x
|
||||
- 1.14.x
|
||||
- 1.15.x
|
||||
201
vendor/github.com/cockroachdb/redact/LICENSE
generated
vendored
Normal file
201
vendor/github.com/cockroachdb/redact/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
5
vendor/github.com/cockroachdb/redact/README.md
generated
vendored
Normal file
5
vendor/github.com/cockroachdb/redact/README.md
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# redact
|
||||
Utilities to redact Go strings for confidentiality
|
||||
|
||||
Godoc link: https://pkg.go.dev/github.com/cockroachdb/redact?tab=doc
|
||||
|
||||
126
vendor/github.com/cockroachdb/redact/api.go
generated
vendored
Normal file
126
vendor/github.com/cockroachdb/redact/api.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import "fmt"
|
||||
|
||||
// SafeFormatter is implemented by object types that want to separate
|
||||
// safe and non-safe information when printed out by a Printf-like
|
||||
// formatter.
|
||||
type SafeFormatter interface {
|
||||
// SafeFormat is like the Format method of fmt.Formatter, except
|
||||
// that it operates using a SafePrinter instead of a fmt.State for
|
||||
// output.
|
||||
//
|
||||
// The verb argument is the control character that defines
|
||||
// the formatting mode in the surrounding Printf call.
|
||||
// For example, if this method is called to format %03d,
|
||||
// the verb is 'd'.
|
||||
SafeFormat(s SafePrinter, verb rune)
|
||||
}
|
||||
|
||||
// SafeValue is a marker interface to be implemented by types that
|
||||
// alias base Go types and whose natural representation via Printf is
|
||||
// always safe for reporting.
|
||||
//
|
||||
// This is recognized by the SafePrinter interface as an alternative
|
||||
// to SafeFormatter.
|
||||
//
|
||||
// It is provided to decorate "leaf" Go types, such as aliases to int.
|
||||
//
|
||||
// Typically, a linter enforces that a type can only implement this
|
||||
// interface if it aliases a base go type. More complex types should
|
||||
// implement SafeFormatter instead.
|
||||
//
|
||||
// It is advised to build an automatic process during builds to
|
||||
// collect all the types that implement this interface, as well as all
|
||||
// uses of this type, and produce a report. Changes to this report
|
||||
// should receive maximal amount of scrutiny during code reviews.
|
||||
type SafeValue interface {
|
||||
SafeValue()
|
||||
}
|
||||
|
||||
// SafeMessager is an alternative to SafeFormatter used in previous
|
||||
// versions of CockroachDB.
|
||||
// NB: this interface is obsolete. Use SafeFormatter instead.
|
||||
// TODO(knz): Remove this.
|
||||
type SafeMessager interface {
|
||||
SafeMessage() string
|
||||
}
|
||||
|
||||
// SafePrinter is a stateful helper that abstracts an output stream in
|
||||
// the context of printf-like formatting, but with the ability to
|
||||
// separate safe and unsafe bits of data.
|
||||
//
|
||||
// This package provides one implementation of this using marker
|
||||
// delimiters for unsafe data, see markers.go. We would like to aim
|
||||
// for alternate implementations to generate more structured formats.
|
||||
type SafePrinter interface {
|
||||
// SafePrinter inherits fmt.State to access format flags, however
|
||||
// calls to fmt.State's underlying Write() as unsafe.
|
||||
fmt.State
|
||||
|
||||
// SafePrinter provides the SafeWriter interface.
|
||||
SafeWriter
|
||||
}
|
||||
|
||||
// SafeWriter provides helper functions for use in implementations of
|
||||
// SafeFormatter, to format mixes of safe and unsafe strings.
|
||||
type SafeWriter interface {
|
||||
// SafeString emits a safe string.
|
||||
SafeString(SafeString)
|
||||
|
||||
// SafeRune emits a safe rune.
|
||||
SafeRune(SafeRune)
|
||||
|
||||
// Print emits its arguments separated by spaces.
|
||||
// For each argument it dynamically checks for the SafeFormatter or
|
||||
// SafeValue interface and either use that, or mark the argument
|
||||
// payload as unsafe.
|
||||
Print(args ...interface{})
|
||||
|
||||
// For printf, a linter checks that the format string is
|
||||
// a constant literal, so the implementation can assume it's always
|
||||
// safe.
|
||||
Printf(format string, arg ...interface{})
|
||||
|
||||
// UnsafeString writes an unsafe string.
|
||||
UnsafeString(string)
|
||||
|
||||
// UnsafeByte writes an unsafe byte.
|
||||
UnsafeByte(byte)
|
||||
|
||||
// UnsafeBytes writes an unsafe byte slice.
|
||||
UnsafeBytes([]byte)
|
||||
|
||||
// UnsafeRune writes an unsafe rune.
|
||||
UnsafeRune(rune)
|
||||
}
|
||||
|
||||
// SafeString aliases string. This is not meant to be used directly;
|
||||
// the type definition ensures that SafePrinter's SafeString method
|
||||
// can only take constant string literals as arguments. Typically, a
|
||||
// Go linter would ensure that ConstantString is never used to cast a
|
||||
// value.
|
||||
type SafeString string
|
||||
|
||||
// SafeValue makes SafeString a SafeValue.
|
||||
func (SafeString) SafeValue() {}
|
||||
|
||||
// SafeRune aliases rune. See the explanation for SafeString.
|
||||
type SafeRune rune
|
||||
|
||||
// SafeValue makes SafeRune a SafeValue.
|
||||
func (SafeRune) SafeValue() {}
|
||||
149
vendor/github.com/cockroachdb/redact/builder.go
generated
vendored
Normal file
149
vendor/github.com/cockroachdb/redact/builder.go
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// StringBuilder accumulates strings with optional redaction markers.
|
||||
//
|
||||
// It implements io.Writer but marks direct writes as redactable.
|
||||
// To distinguish safe and unsafe bits, it also implements the SafeWriter
|
||||
// interface.
|
||||
type StringBuilder struct {
|
||||
// we use bytes.Buffer internally to simplify the implementation of
|
||||
// the SafeWriter interface.
|
||||
buf bytes.Buffer
|
||||
}
|
||||
|
||||
// String returns the accumulated string, with redaction markers stripped out.
|
||||
// To obtain the redactable string, call RedactableString().
|
||||
func (b StringBuilder) String() string { return b.RedactableString().StripMarkers() }
|
||||
|
||||
var _ fmt.Stringer = StringBuilder{}
|
||||
var _ fmt.Stringer = (*StringBuilder)(nil)
|
||||
|
||||
// RedactableString returns the accumulated string, including redaction markers.
|
||||
func (b StringBuilder) RedactableString() RedactableString { return RedactableString(b.buf.String()) }
|
||||
|
||||
// RedactableBytes returns the accumulated bytes, including redaction markers.
|
||||
func (b StringBuilder) RedactableBytes() RedactableBytes { return RedactableBytes(b.buf.Bytes()) }
|
||||
|
||||
// SafeFormat implements SafeFormatter.
|
||||
func (b StringBuilder) SafeFormat(p SafePrinter, _ rune) {
|
||||
// We only support the %v / %s natural print here.
|
||||
// Go supports other formatting verbs for strings: %x/%X/%q.
|
||||
//
|
||||
// We don't do this here, keeping in mind that the output
|
||||
// of a SafeFormat must remain a redactable string.
|
||||
//
|
||||
// %x/%X cannot be implemented because they would turn redaction
|
||||
// markers into hex codes, and the entire result string would
|
||||
// appear safe for reporting, which would break the semantics
|
||||
// of this package.
|
||||
//
|
||||
// %q cannot be implemented because it replaces non-ASCII characters
|
||||
// with numeric unicode escapes, which breaks redaction
|
||||
// markers too.
|
||||
p.Print(b.RedactableString())
|
||||
}
|
||||
|
||||
var _ SafeFormatter = StringBuilder{}
|
||||
var _ SafeFormatter = (*StringBuilder)(nil)
|
||||
|
||||
// Len returns the number of accumulated bytes, including redaction
|
||||
// markers; b.Len() == len(b.RedactableString()).
|
||||
func (b *StringBuilder) Len() int { return b.buf.Len() }
|
||||
|
||||
// Cap returns the capacity of the builder's underlying byte slice. It is the
|
||||
// total space allocated for the string being built and includes any bytes
|
||||
// already written.
|
||||
func (b *StringBuilder) Cap() int { return b.buf.Cap() }
|
||||
|
||||
// Reset resets the Builder to be empty.
|
||||
func (b *StringBuilder) Reset() { b.buf.Reset() }
|
||||
|
||||
// StringBuilder implements io.Writer.
|
||||
// Direct Write() calls are considered unsafe.
|
||||
var _ io.Writer = (*StringBuilder)(nil)
|
||||
|
||||
// Write implements the io.Writer interface.
|
||||
func (b *StringBuilder) Write(s []byte) (int, error) {
|
||||
b.UnsafeBytes(s)
|
||||
return len(s), nil
|
||||
}
|
||||
|
||||
// StringBuilder implements SafeWriter.
|
||||
var _ SafeWriter = (*StringBuilder)(nil)
|
||||
|
||||
// Print is part of the SafeWriter interface.
|
||||
func (b *StringBuilder) Print(args ...interface{}) {
|
||||
_, _ = Fprint(&b.buf, args...)
|
||||
}
|
||||
|
||||
// Printf is part of the SafeWriter interface.
|
||||
func (b *StringBuilder) Printf(format string, args ...interface{}) {
|
||||
_, _ = Fprintf(&b.buf, format, args...)
|
||||
}
|
||||
|
||||
// SafeString is part of the SafeWriter interface.
|
||||
func (b *StringBuilder) SafeString(s SafeString) {
|
||||
w := escapeWriter{w: &b.buf, enclose: false}
|
||||
_, _ = w.Write([]byte(s))
|
||||
}
|
||||
|
||||
// SafeRune is part of the SafeWriter interface.
|
||||
func (b *StringBuilder) SafeRune(s SafeRune) {
|
||||
if s == startRedactable || s == endRedactable {
|
||||
s = escapeMark
|
||||
}
|
||||
_, _ = b.buf.WriteRune(rune(s))
|
||||
}
|
||||
|
||||
// UnsafeString is part of the SafeWriter interface.
|
||||
func (b *StringBuilder) UnsafeString(s string) {
|
||||
w := escapeWriter{w: &b.buf, enclose: true, strip: true}
|
||||
_, _ = w.Write([]byte(s))
|
||||
}
|
||||
|
||||
// UnsafeRune is part of the SafeWriter interface.
|
||||
func (b *StringBuilder) UnsafeRune(s rune) {
|
||||
_, _ = b.buf.WriteRune(startRedactable)
|
||||
b.SafeRune(SafeRune(s))
|
||||
_, _ = b.buf.WriteRune(endRedactable)
|
||||
}
|
||||
|
||||
// UnsafeByte is part of the SafeWriter interface.
|
||||
func (b *StringBuilder) UnsafeByte(s byte) {
|
||||
_, _ = b.buf.WriteRune(startRedactable)
|
||||
if s >= utf8.RuneSelf ||
|
||||
s == startRedactableBytes[0] || s == endRedactableBytes[0] {
|
||||
// Unsafe byte. Escape it.
|
||||
_, _ = b.buf.Write(escapeBytes)
|
||||
} else {
|
||||
_ = b.buf.WriteByte(s)
|
||||
}
|
||||
_, _ = b.buf.WriteRune(endRedactable)
|
||||
}
|
||||
|
||||
// UnsafeBytes is part of the SafeWriter interface.
|
||||
func (b *StringBuilder) UnsafeBytes(s []byte) {
|
||||
w := escapeWriter{w: &b.buf, enclose: true, strip: true}
|
||||
_, _ = w.Write(s)
|
||||
}
|
||||
51
vendor/github.com/cockroachdb/redact/doc.go
generated
vendored
Normal file
51
vendor/github.com/cockroachdb/redact/doc.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
// Package redact provides facilities for separating “safe” and
|
||||
// “unsafe” pieces of data when logging and constructing error object.
|
||||
//
|
||||
// An item is said to be “safe” if it is proven to not contain
|
||||
// PII or otherwise confidential information that should not escape
|
||||
// the boundaries of the current system, for example via telemetry
|
||||
// or crash reporting. Conversely, data is considered “unsafe”
|
||||
// until/unless it is known to be “safe”.
|
||||
//
|
||||
// Example use:
|
||||
//
|
||||
// redactable := redact.Sprintf("hello %s", "universe")
|
||||
//
|
||||
// // At this point, 'redactable' contains "hello ‹universe›".
|
||||
//
|
||||
// // This prints "hello universe":
|
||||
// fmt.Println(redactable.StripMarkers())
|
||||
//
|
||||
// // This reports "hello ‹×›":
|
||||
// fmt.Println(redactable.Redact())
|
||||
//
|
||||
//
|
||||
// When defining your own custom types, you can define
|
||||
// a SafeFormat method, implementing the redact.SafeFormatter
|
||||
// interface in a way you'd otherwise implement fmt.Formatter.
|
||||
// This is then recognized by this package's API automatically.
|
||||
//
|
||||
// Alternatively:
|
||||
//
|
||||
// - you can implement the SafeValue interface, which tells the
|
||||
// redact package to always the default formatting of a type
|
||||
// as safe and thus not included inside redaction markers.
|
||||
//
|
||||
// - you can include a value within redact.Safe() and redact.Unsafe()
|
||||
// in redact.Sprintf / redact.Fprintf calls, to force
|
||||
// the omission or inclusion of redaction markers.
|
||||
package redact
|
||||
52
vendor/github.com/cockroachdb/redact/internal/README.md
generated
vendored
Normal file
52
vendor/github.com/cockroachdb/redact/internal/README.md
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
Overall code structure
|
||||
======================
|
||||
|
||||
This directory imports the "printf" logic as-is from the Go standard
|
||||
library and instruments it for redaction of sensitive data.
|
||||
|
||||
Overall, the original Go code is structured as follows:
|
||||
|
||||
- the top-level API functions (`Printf` `Fprintf` etc) instantiate a
|
||||
"printer" struct called `pp`, then call the `doPrint*()` methods
|
||||
on it.
|
||||
|
||||
- the `pp` contains a byte slice (`pp.buf`, type `buffer`) that
|
||||
accumulates the result of formatting *regardless of the final output
|
||||
of the API* - i.e. a buffer is used even when using `Fprint` to an
|
||||
`io.Writer`. Only after the `doPrint()` method finishes, is the
|
||||
`buffer` copied to the final `io.Writer` in the `Fprint*` variants.
|
||||
|
||||
- each of the `doPrint` methods does some analysis on the argument
|
||||
list - quite simple for e.g. `doPrintln`, more intricate for
|
||||
`doPrintf`. As part of the analysis it emits "spacing" or no-op
|
||||
bytes directly on the `pp.buf`. For example `doPrint` emits spaces
|
||||
between arguments directly, `doPrintf` emits the non-formatting
|
||||
characters from the format string, as well as certain *constant*
|
||||
error strings (e.g. `%(BADPREC)`).
|
||||
|
||||
At this point **we make the following assumption**: there is no data
|
||||
from the printed *arguments* that is emitted to `pp.buf` directly by a
|
||||
`doPrint()` method. This is true of the implementation as of Go 1.14.
|
||||
|
||||
From this point, this package contains a *custom patch* onto the
|
||||
default implementation: the calls to `p.printArg` performed by the
|
||||
`doPrint()` methods are redirected to a function callback that is
|
||||
injected by the `redact` package.
|
||||
|
||||
Refreshing the sources
|
||||
======================
|
||||
|
||||
The files in this directory have been imported from
|
||||
|
||||
`$GOROOT/src/fmt/{format,print}.go`
|
||||
|
||||
and
|
||||
|
||||
`$GOROOT/src/internal/fmtsort`
|
||||
|
||||
And patched using the included `.diff` files.
|
||||
|
||||
To upgrade to a newer Go implementation, import the files anew and
|
||||
re-apply the patches.
|
||||
|
||||
See the script `refresh.sh` for details.
|
||||
222
vendor/github.com/cockroachdb/redact/internal/fmtsort/sort.go
generated
vendored
Normal file
222
vendor/github.com/cockroachdb/redact/internal/fmtsort/sort.go
generated
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
// Code generated from the Go standard library. DO NOT EDIT
|
||||
// GENERATED FILE DO NOT EDIT
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package fmtsort provides a general stable ordering mechanism
|
||||
// for maps, on behalf of the fmt and text/template packages.
|
||||
// It is not guaranteed to be efficient and works only for types
|
||||
// that are valid map keys.
|
||||
package fmtsort
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Note: Throughout this package we avoid calling reflect.Value.Interface as
|
||||
// it is not always legal to do so and it's easier to avoid the issue than to face it.
|
||||
|
||||
// SortedMap represents a map's keys and values. The keys and values are
|
||||
// aligned in index order: Value[i] is the value in the map corresponding to Key[i].
|
||||
type SortedMap struct {
|
||||
Key []reflect.Value
|
||||
Value []reflect.Value
|
||||
}
|
||||
|
||||
func (o *SortedMap) Len() int { return len(o.Key) }
|
||||
func (o *SortedMap) Less(i, j int) bool { return compare(o.Key[i], o.Key[j]) < 0 }
|
||||
func (o *SortedMap) Swap(i, j int) {
|
||||
o.Key[i], o.Key[j] = o.Key[j], o.Key[i]
|
||||
o.Value[i], o.Value[j] = o.Value[j], o.Value[i]
|
||||
}
|
||||
|
||||
// Sort accepts a map and returns a SortedMap that has the same keys and
|
||||
// values but in a stable sorted order according to the keys, modulo issues
|
||||
// raised by unorderable key values such as NaNs.
|
||||
//
|
||||
// The ordering rules are more general than with Go's < operator:
|
||||
//
|
||||
// - when applicable, nil compares low
|
||||
// - ints, floats, and strings order by <
|
||||
// - NaN compares less than non-NaN floats
|
||||
// - bool compares false before true
|
||||
// - complex compares real, then imag
|
||||
// - pointers compare by machine address
|
||||
// - channel values compare by machine address
|
||||
// - structs compare each field in turn
|
||||
// - arrays compare each element in turn.
|
||||
// Otherwise identical arrays compare by length.
|
||||
// - interface values compare first by reflect.Type describing the concrete type
|
||||
// and then by concrete value as described in the previous rules.
|
||||
//
|
||||
func Sort(mapValue reflect.Value) *SortedMap {
|
||||
if mapValue.Type().Kind() != reflect.Map {
|
||||
return nil
|
||||
}
|
||||
// Note: this code is arranged to not panic even in the presence
|
||||
// of a concurrent map update. The runtime is responsible for
|
||||
// yelling loudly if that happens. See issue 33275.
|
||||
n := mapValue.Len()
|
||||
key := make([]reflect.Value, 0, n)
|
||||
value := make([]reflect.Value, 0, n)
|
||||
iter := mapValue.MapRange()
|
||||
for iter.Next() {
|
||||
key = append(key, iter.Key())
|
||||
value = append(value, iter.Value())
|
||||
}
|
||||
sorted := &SortedMap{
|
||||
Key: key,
|
||||
Value: value,
|
||||
}
|
||||
sort.Stable(sorted)
|
||||
return sorted
|
||||
}
|
||||
|
||||
// compare compares two values of the same type. It returns -1, 0, 1
|
||||
// according to whether a > b (1), a == b (0), or a < b (-1).
|
||||
// If the types differ, it returns -1.
|
||||
// See the comment on Sort for the comparison rules.
|
||||
func compare(aVal, bVal reflect.Value) int {
|
||||
aType, bType := aVal.Type(), bVal.Type()
|
||||
if aType != bType {
|
||||
return -1 // No good answer possible, but don't return 0: they're not equal.
|
||||
}
|
||||
switch aVal.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
a, b := aVal.Int(), bVal.Int()
|
||||
switch {
|
||||
case a < b:
|
||||
return -1
|
||||
case a > b:
|
||||
return 1
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
a, b := aVal.Uint(), bVal.Uint()
|
||||
switch {
|
||||
case a < b:
|
||||
return -1
|
||||
case a > b:
|
||||
return 1
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
case reflect.String:
|
||||
a, b := aVal.String(), bVal.String()
|
||||
switch {
|
||||
case a < b:
|
||||
return -1
|
||||
case a > b:
|
||||
return 1
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return floatCompare(aVal.Float(), bVal.Float())
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
a, b := aVal.Complex(), bVal.Complex()
|
||||
if c := floatCompare(real(a), real(b)); c != 0 {
|
||||
return c
|
||||
}
|
||||
return floatCompare(imag(a), imag(b))
|
||||
case reflect.Bool:
|
||||
a, b := aVal.Bool(), bVal.Bool()
|
||||
switch {
|
||||
case a == b:
|
||||
return 0
|
||||
case a:
|
||||
return 1
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
case reflect.Ptr:
|
||||
a, b := aVal.Pointer(), bVal.Pointer()
|
||||
switch {
|
||||
case a < b:
|
||||
return -1
|
||||
case a > b:
|
||||
return 1
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
case reflect.Chan:
|
||||
if c, ok := nilCompare(aVal, bVal); ok {
|
||||
return c
|
||||
}
|
||||
ap, bp := aVal.Pointer(), bVal.Pointer()
|
||||
switch {
|
||||
case ap < bp:
|
||||
return -1
|
||||
case ap > bp:
|
||||
return 1
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
case reflect.Struct:
|
||||
for i := 0; i < aVal.NumField(); i++ {
|
||||
if c := compare(aVal.Field(i), bVal.Field(i)); c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return 0
|
||||
case reflect.Array:
|
||||
for i := 0; i < aVal.Len(); i++ {
|
||||
if c := compare(aVal.Index(i), bVal.Index(i)); c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return 0
|
||||
case reflect.Interface:
|
||||
if c, ok := nilCompare(aVal, bVal); ok {
|
||||
return c
|
||||
}
|
||||
c := compare(reflect.ValueOf(aVal.Elem().Type()), reflect.ValueOf(bVal.Elem().Type()))
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
return compare(aVal.Elem(), bVal.Elem())
|
||||
default:
|
||||
// Certain types cannot appear as keys (maps, funcs, slices), but be explicit.
|
||||
panic("bad type in compare: " + aType.String())
|
||||
}
|
||||
}
|
||||
|
||||
// nilCompare checks whether either value is nil. If not, the boolean is false.
|
||||
// If either value is nil, the boolean is true and the integer is the comparison
|
||||
// value. The comparison is defined to be 0 if both are nil, otherwise the one
|
||||
// nil value compares low. Both arguments must represent a chan, func,
|
||||
// interface, map, pointer, or slice.
|
||||
func nilCompare(aVal, bVal reflect.Value) (int, bool) {
|
||||
if aVal.IsNil() {
|
||||
if bVal.IsNil() {
|
||||
return 0, true
|
||||
}
|
||||
return -1, true
|
||||
}
|
||||
if bVal.IsNil() {
|
||||
return 1, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// floatCompare compares two floating-point values. NaNs compare low.
|
||||
func floatCompare(a, b float64) int {
|
||||
switch {
|
||||
case isNaN(a):
|
||||
return -1 // No good answer if b is a NaN so don't bother checking.
|
||||
case isNaN(b):
|
||||
return 1
|
||||
case a < b:
|
||||
return -1
|
||||
case a > b:
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func isNaN(a float64) bool {
|
||||
return a != a
|
||||
}
|
||||
595
vendor/github.com/cockroachdb/redact/internal/format.go
generated
vendored
Normal file
595
vendor/github.com/cockroachdb/redact/internal/format.go
generated
vendored
Normal file
@@ -0,0 +1,595 @@
|
||||
// Code generated from the Go standard library. DO NOT EDIT
|
||||
// GENERATED FILE DO NOT EDIT
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fmt
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
ldigits = "0123456789abcdefx"
|
||||
udigits = "0123456789ABCDEFX"
|
||||
)
|
||||
|
||||
const (
|
||||
signed = true
|
||||
unsigned = false
|
||||
)
|
||||
|
||||
// flags placed in a separate struct for easy clearing.
|
||||
type fmtFlags struct {
|
||||
widPresent bool
|
||||
precPresent bool
|
||||
minus bool
|
||||
plus bool
|
||||
sharp bool
|
||||
space bool
|
||||
zero bool
|
||||
|
||||
// For the formats %+v %#v, we set the plusV/sharpV flags
|
||||
// and clear the plus/sharp flags since %+v and %#v are in effect
|
||||
// different, flagless formats set at the top level.
|
||||
plusV bool
|
||||
sharpV bool
|
||||
}
|
||||
|
||||
// A fmt is the raw formatter used by Printf etc.
|
||||
// It prints into a buffer that must be set up separately.
|
||||
type fmt struct {
|
||||
buf *buffer
|
||||
|
||||
fmtFlags
|
||||
|
||||
wid int // width
|
||||
prec int // precision
|
||||
|
||||
// intbuf is large enough to store %b of an int64 with a sign and
|
||||
// avoids padding at the end of the struct on 32 bit architectures.
|
||||
intbuf [68]byte
|
||||
}
|
||||
|
||||
func (f *fmt) clearflags() {
|
||||
f.fmtFlags = fmtFlags{}
|
||||
}
|
||||
|
||||
func (f *fmt) init(buf *buffer) {
|
||||
f.buf = buf
|
||||
f.clearflags()
|
||||
}
|
||||
|
||||
// writePadding generates n bytes of padding.
|
||||
func (f *fmt) writePadding(n int) {
|
||||
if n <= 0 { // No padding bytes needed.
|
||||
return
|
||||
}
|
||||
buf := *f.buf
|
||||
oldLen := len(buf)
|
||||
newLen := oldLen + n
|
||||
// Make enough room for padding.
|
||||
if newLen > cap(buf) {
|
||||
buf = make(buffer, cap(buf)*2+n)
|
||||
copy(buf, *f.buf)
|
||||
}
|
||||
// Decide which byte the padding should be filled with.
|
||||
padByte := byte(' ')
|
||||
if f.zero {
|
||||
padByte = byte('0')
|
||||
}
|
||||
// Fill padding with padByte.
|
||||
padding := buf[oldLen:newLen]
|
||||
for i := range padding {
|
||||
padding[i] = padByte
|
||||
}
|
||||
*f.buf = buf[:newLen]
|
||||
}
|
||||
|
||||
// pad appends b to f.buf, padded on left (!f.minus) or right (f.minus).
|
||||
func (f *fmt) pad(b []byte) {
|
||||
if !f.widPresent || f.wid == 0 {
|
||||
f.buf.write(b)
|
||||
return
|
||||
}
|
||||
width := f.wid - utf8.RuneCount(b)
|
||||
if !f.minus {
|
||||
// left padding
|
||||
f.writePadding(width)
|
||||
f.buf.write(b)
|
||||
} else {
|
||||
// right padding
|
||||
f.buf.write(b)
|
||||
f.writePadding(width)
|
||||
}
|
||||
}
|
||||
|
||||
// padString appends s to f.buf, padded on left (!f.minus) or right (f.minus).
|
||||
func (f *fmt) padString(s string) {
|
||||
if !f.widPresent || f.wid == 0 {
|
||||
f.buf.writeString(s)
|
||||
return
|
||||
}
|
||||
width := f.wid - utf8.RuneCountInString(s)
|
||||
if !f.minus {
|
||||
// left padding
|
||||
f.writePadding(width)
|
||||
f.buf.writeString(s)
|
||||
} else {
|
||||
// right padding
|
||||
f.buf.writeString(s)
|
||||
f.writePadding(width)
|
||||
}
|
||||
}
|
||||
|
||||
// fmtBoolean formats a boolean.
|
||||
func (f *fmt) fmtBoolean(v bool) {
|
||||
if v {
|
||||
f.padString("true")
|
||||
} else {
|
||||
f.padString("false")
|
||||
}
|
||||
}
|
||||
|
||||
// fmtUnicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'".
|
||||
func (f *fmt) fmtUnicode(u uint64) {
|
||||
buf := f.intbuf[0:]
|
||||
|
||||
// With default precision set the maximum needed buf length is 18
|
||||
// for formatting -1 with %#U ("U+FFFFFFFFFFFFFFFF") which fits
|
||||
// into the already allocated intbuf with a capacity of 68 bytes.
|
||||
prec := 4
|
||||
if f.precPresent && f.prec > 4 {
|
||||
prec = f.prec
|
||||
// Compute space needed for "U+" , number, " '", character, "'".
|
||||
width := 2 + prec + 2 + utf8.UTFMax + 1
|
||||
if width > len(buf) {
|
||||
buf = make([]byte, width)
|
||||
}
|
||||
}
|
||||
|
||||
// Format into buf, ending at buf[i]. Formatting numbers is easier right-to-left.
|
||||
i := len(buf)
|
||||
|
||||
// For %#U we want to add a space and a quoted character at the end of the buffer.
|
||||
if f.sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) {
|
||||
i--
|
||||
buf[i] = '\''
|
||||
i -= utf8.RuneLen(rune(u))
|
||||
utf8.EncodeRune(buf[i:], rune(u))
|
||||
i--
|
||||
buf[i] = '\''
|
||||
i--
|
||||
buf[i] = ' '
|
||||
}
|
||||
// Format the Unicode code point u as a hexadecimal number.
|
||||
for u >= 16 {
|
||||
i--
|
||||
buf[i] = udigits[u&0xF]
|
||||
prec--
|
||||
u >>= 4
|
||||
}
|
||||
i--
|
||||
buf[i] = udigits[u]
|
||||
prec--
|
||||
// Add zeros in front of the number until requested precision is reached.
|
||||
for prec > 0 {
|
||||
i--
|
||||
buf[i] = '0'
|
||||
prec--
|
||||
}
|
||||
// Add a leading "U+".
|
||||
i--
|
||||
buf[i] = '+'
|
||||
i--
|
||||
buf[i] = 'U'
|
||||
|
||||
oldZero := f.zero
|
||||
f.zero = false
|
||||
f.pad(buf[i:])
|
||||
f.zero = oldZero
|
||||
}
|
||||
|
||||
// fmtInteger formats signed and unsigned integers.
|
||||
func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, verb rune, digits string) {
|
||||
negative := isSigned && int64(u) < 0
|
||||
if negative {
|
||||
u = -u
|
||||
}
|
||||
|
||||
buf := f.intbuf[0:]
|
||||
// The already allocated f.intbuf with a capacity of 68 bytes
|
||||
// is large enough for integer formatting when no precision or width is set.
|
||||
if f.widPresent || f.precPresent {
|
||||
// Account 3 extra bytes for possible addition of a sign and "0x".
|
||||
width := 3 + f.wid + f.prec // wid and prec are always positive.
|
||||
if width > len(buf) {
|
||||
// We're going to need a bigger boat.
|
||||
buf = make([]byte, width)
|
||||
}
|
||||
}
|
||||
|
||||
// Two ways to ask for extra leading zero digits: %.3d or %03d.
|
||||
// If both are specified the f.zero flag is ignored and
|
||||
// padding with spaces is used instead.
|
||||
prec := 0
|
||||
if f.precPresent {
|
||||
prec = f.prec
|
||||
// Precision of 0 and value of 0 means "print nothing" but padding.
|
||||
if prec == 0 && u == 0 {
|
||||
oldZero := f.zero
|
||||
f.zero = false
|
||||
f.writePadding(f.wid)
|
||||
f.zero = oldZero
|
||||
return
|
||||
}
|
||||
} else if f.zero && f.widPresent {
|
||||
prec = f.wid
|
||||
if negative || f.plus || f.space {
|
||||
prec-- // leave room for sign
|
||||
}
|
||||
}
|
||||
|
||||
// Because printing is easier right-to-left: format u into buf, ending at buf[i].
|
||||
// We could make things marginally faster by splitting the 32-bit case out
|
||||
// into a separate block but it's not worth the duplication, so u has 64 bits.
|
||||
i := len(buf)
|
||||
// Use constants for the division and modulo for more efficient code.
|
||||
// Switch cases ordered by popularity.
|
||||
switch base {
|
||||
case 10:
|
||||
for u >= 10 {
|
||||
i--
|
||||
next := u / 10
|
||||
buf[i] = byte('0' + u - next*10)
|
||||
u = next
|
||||
}
|
||||
case 16:
|
||||
for u >= 16 {
|
||||
i--
|
||||
buf[i] = digits[u&0xF]
|
||||
u >>= 4
|
||||
}
|
||||
case 8:
|
||||
for u >= 8 {
|
||||
i--
|
||||
buf[i] = byte('0' + u&7)
|
||||
u >>= 3
|
||||
}
|
||||
case 2:
|
||||
for u >= 2 {
|
||||
i--
|
||||
buf[i] = byte('0' + u&1)
|
||||
u >>= 1
|
||||
}
|
||||
default:
|
||||
panic("fmt: unknown base; can't happen")
|
||||
}
|
||||
i--
|
||||
buf[i] = digits[u]
|
||||
for i > 0 && prec > len(buf)-i {
|
||||
i--
|
||||
buf[i] = '0'
|
||||
}
|
||||
|
||||
// Various prefixes: 0x, -, etc.
|
||||
if f.sharp {
|
||||
switch base {
|
||||
case 2:
|
||||
// Add a leading 0b.
|
||||
i--
|
||||
buf[i] = 'b'
|
||||
i--
|
||||
buf[i] = '0'
|
||||
case 8:
|
||||
if buf[i] != '0' {
|
||||
i--
|
||||
buf[i] = '0'
|
||||
}
|
||||
case 16:
|
||||
// Add a leading 0x or 0X.
|
||||
i--
|
||||
buf[i] = digits[16]
|
||||
i--
|
||||
buf[i] = '0'
|
||||
}
|
||||
}
|
||||
if verb == 'O' {
|
||||
i--
|
||||
buf[i] = 'o'
|
||||
i--
|
||||
buf[i] = '0'
|
||||
}
|
||||
|
||||
if negative {
|
||||
i--
|
||||
buf[i] = '-'
|
||||
} else if f.plus {
|
||||
i--
|
||||
buf[i] = '+'
|
||||
} else if f.space {
|
||||
i--
|
||||
buf[i] = ' '
|
||||
}
|
||||
|
||||
// Left padding with zeros has already been handled like precision earlier
|
||||
// or the f.zero flag is ignored due to an explicitly set precision.
|
||||
oldZero := f.zero
|
||||
f.zero = false
|
||||
f.pad(buf[i:])
|
||||
f.zero = oldZero
|
||||
}
|
||||
|
||||
// truncate truncates the string s to the specified precision, if present.
|
||||
func (f *fmt) truncateString(s string) string {
|
||||
if f.precPresent {
|
||||
n := f.prec
|
||||
for i := range s {
|
||||
n--
|
||||
if n < 0 {
|
||||
return s[:i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// truncate truncates the byte slice b as a string of the specified precision, if present.
|
||||
func (f *fmt) truncate(b []byte) []byte {
|
||||
if f.precPresent {
|
||||
n := f.prec
|
||||
for i := 0; i < len(b); {
|
||||
n--
|
||||
if n < 0 {
|
||||
return b[:i]
|
||||
}
|
||||
wid := 1
|
||||
if b[i] >= utf8.RuneSelf {
|
||||
_, wid = utf8.DecodeRune(b[i:])
|
||||
}
|
||||
i += wid
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// fmtS formats a string.
|
||||
func (f *fmt) fmtS(s string) {
|
||||
s = f.truncateString(s)
|
||||
f.padString(s)
|
||||
}
|
||||
|
||||
// fmtBs formats the byte slice b as if it was formatted as string with fmtS.
|
||||
func (f *fmt) fmtBs(b []byte) {
|
||||
b = f.truncate(b)
|
||||
f.pad(b)
|
||||
}
|
||||
|
||||
// fmtSbx formats a string or byte slice as a hexadecimal encoding of its bytes.
|
||||
func (f *fmt) fmtSbx(s string, b []byte, digits string) {
|
||||
length := len(b)
|
||||
if b == nil {
|
||||
// No byte slice present. Assume string s should be encoded.
|
||||
length = len(s)
|
||||
}
|
||||
// Set length to not process more bytes than the precision demands.
|
||||
if f.precPresent && f.prec < length {
|
||||
length = f.prec
|
||||
}
|
||||
// Compute width of the encoding taking into account the f.sharp and f.space flag.
|
||||
width := 2 * length
|
||||
if width > 0 {
|
||||
if f.space {
|
||||
// Each element encoded by two hexadecimals will get a leading 0x or 0X.
|
||||
if f.sharp {
|
||||
width *= 2
|
||||
}
|
||||
// Elements will be separated by a space.
|
||||
width += length - 1
|
||||
} else if f.sharp {
|
||||
// Only a leading 0x or 0X will be added for the whole string.
|
||||
width += 2
|
||||
}
|
||||
} else { // The byte slice or string that should be encoded is empty.
|
||||
if f.widPresent {
|
||||
f.writePadding(f.wid)
|
||||
}
|
||||
return
|
||||
}
|
||||
// Handle padding to the left.
|
||||
if f.widPresent && f.wid > width && !f.minus {
|
||||
f.writePadding(f.wid - width)
|
||||
}
|
||||
// Write the encoding directly into the output buffer.
|
||||
buf := *f.buf
|
||||
if f.sharp {
|
||||
// Add leading 0x or 0X.
|
||||
buf = append(buf, '0', digits[16])
|
||||
}
|
||||
var c byte
|
||||
for i := 0; i < length; i++ {
|
||||
if f.space && i > 0 {
|
||||
// Separate elements with a space.
|
||||
buf = append(buf, ' ')
|
||||
if f.sharp {
|
||||
// Add leading 0x or 0X for each element.
|
||||
buf = append(buf, '0', digits[16])
|
||||
}
|
||||
}
|
||||
if b != nil {
|
||||
c = b[i] // Take a byte from the input byte slice.
|
||||
} else {
|
||||
c = s[i] // Take a byte from the input string.
|
||||
}
|
||||
// Encode each byte as two hexadecimal digits.
|
||||
buf = append(buf, digits[c>>4], digits[c&0xF])
|
||||
}
|
||||
*f.buf = buf
|
||||
// Handle padding to the right.
|
||||
if f.widPresent && f.wid > width && f.minus {
|
||||
f.writePadding(f.wid - width)
|
||||
}
|
||||
}
|
||||
|
||||
// fmtSx formats a string as a hexadecimal encoding of its bytes.
|
||||
func (f *fmt) fmtSx(s, digits string) {
|
||||
f.fmtSbx(s, nil, digits)
|
||||
}
|
||||
|
||||
// fmtBx formats a byte slice as a hexadecimal encoding of its bytes.
|
||||
func (f *fmt) fmtBx(b []byte, digits string) {
|
||||
f.fmtSbx("", b, digits)
|
||||
}
|
||||
|
||||
// fmtQ formats a string as a double-quoted, escaped Go string constant.
|
||||
// If f.sharp is set a raw (backquoted) string may be returned instead
|
||||
// if the string does not contain any control characters other than tab.
|
||||
func (f *fmt) fmtQ(s string) {
|
||||
s = f.truncateString(s)
|
||||
if f.sharp && strconv.CanBackquote(s) {
|
||||
f.padString("`" + s + "`")
|
||||
return
|
||||
}
|
||||
buf := f.intbuf[:0]
|
||||
if f.plus {
|
||||
f.pad(strconv.AppendQuoteToASCII(buf, s))
|
||||
} else {
|
||||
f.pad(strconv.AppendQuote(buf, s))
|
||||
}
|
||||
}
|
||||
|
||||
// fmtC formats an integer as a Unicode character.
|
||||
// If the character is not valid Unicode, it will print '\ufffd'.
|
||||
func (f *fmt) fmtC(c uint64) {
|
||||
r := rune(c)
|
||||
if c > utf8.MaxRune {
|
||||
r = utf8.RuneError
|
||||
}
|
||||
buf := f.intbuf[:0]
|
||||
w := utf8.EncodeRune(buf[:utf8.UTFMax], r)
|
||||
f.pad(buf[:w])
|
||||
}
|
||||
|
||||
// fmtQc formats an integer as a single-quoted, escaped Go character constant.
|
||||
// If the character is not valid Unicode, it will print '\ufffd'.
|
||||
func (f *fmt) fmtQc(c uint64) {
|
||||
r := rune(c)
|
||||
if c > utf8.MaxRune {
|
||||
r = utf8.RuneError
|
||||
}
|
||||
buf := f.intbuf[:0]
|
||||
if f.plus {
|
||||
f.pad(strconv.AppendQuoteRuneToASCII(buf, r))
|
||||
} else {
|
||||
f.pad(strconv.AppendQuoteRune(buf, r))
|
||||
}
|
||||
}
|
||||
|
||||
// fmtFloat formats a float64. It assumes that verb is a valid format specifier
|
||||
// for strconv.AppendFloat and therefore fits into a byte.
|
||||
func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
|
||||
// Explicit precision in format specifier overrules default precision.
|
||||
if f.precPresent {
|
||||
prec = f.prec
|
||||
}
|
||||
// Format number, reserving space for leading + sign if needed.
|
||||
num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size)
|
||||
if num[1] == '-' || num[1] == '+' {
|
||||
num = num[1:]
|
||||
} else {
|
||||
num[0] = '+'
|
||||
}
|
||||
// f.space means to add a leading space instead of a "+" sign unless
|
||||
// the sign is explicitly asked for by f.plus.
|
||||
if f.space && num[0] == '+' && !f.plus {
|
||||
num[0] = ' '
|
||||
}
|
||||
// Special handling for infinities and NaN,
|
||||
// which don't look like a number so shouldn't be padded with zeros.
|
||||
if num[1] == 'I' || num[1] == 'N' {
|
||||
oldZero := f.zero
|
||||
f.zero = false
|
||||
// Remove sign before NaN if not asked for.
|
||||
if num[1] == 'N' && !f.space && !f.plus {
|
||||
num = num[1:]
|
||||
}
|
||||
f.pad(num)
|
||||
f.zero = oldZero
|
||||
return
|
||||
}
|
||||
// The sharp flag forces printing a decimal point for non-binary formats
|
||||
// and retains trailing zeros, which we may need to restore.
|
||||
if f.sharp && verb != 'b' {
|
||||
digits := 0
|
||||
switch verb {
|
||||
case 'v', 'g', 'G', 'x':
|
||||
digits = prec
|
||||
// If no precision is set explicitly use a precision of 6.
|
||||
if digits == -1 {
|
||||
digits = 6
|
||||
}
|
||||
}
|
||||
|
||||
// Buffer pre-allocated with enough room for
|
||||
// exponent notations of the form "e+123" or "p-1023".
|
||||
var tailBuf [6]byte
|
||||
tail := tailBuf[:0]
|
||||
|
||||
hasDecimalPoint := false
|
||||
sawNonzeroDigit := false
|
||||
// Starting from i = 1 to skip sign at num[0].
|
||||
for i := 1; i < len(num); i++ {
|
||||
switch num[i] {
|
||||
case '.':
|
||||
hasDecimalPoint = true
|
||||
case 'p', 'P':
|
||||
tail = append(tail, num[i:]...)
|
||||
num = num[:i]
|
||||
case 'e', 'E':
|
||||
if verb != 'x' && verb != 'X' {
|
||||
tail = append(tail, num[i:]...)
|
||||
num = num[:i]
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
if num[i] != '0' {
|
||||
sawNonzeroDigit = true
|
||||
}
|
||||
// Count significant digits after the first non-zero digit.
|
||||
if sawNonzeroDigit {
|
||||
digits--
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hasDecimalPoint {
|
||||
// Leading digit 0 should contribute once to digits.
|
||||
if len(num) == 2 && num[1] == '0' {
|
||||
digits--
|
||||
}
|
||||
num = append(num, '.')
|
||||
}
|
||||
for digits > 0 {
|
||||
num = append(num, '0')
|
||||
digits--
|
||||
}
|
||||
num = append(num, tail...)
|
||||
}
|
||||
// We want a sign if asked for and if the sign is not positive.
|
||||
if f.plus || num[0] != '+' {
|
||||
// If we're zero padding to the left we want the sign before the leading zeros.
|
||||
// Achieve this by writing the sign out and then padding the unsigned number.
|
||||
if f.zero && f.widPresent && f.wid > len(num) {
|
||||
f.buf.writeByte(num[0])
|
||||
f.writePadding(f.wid - len(num))
|
||||
f.buf.write(num[1:])
|
||||
return
|
||||
}
|
||||
f.pad(num)
|
||||
return
|
||||
}
|
||||
// No sign to show and the number is positive; just print the unsigned number.
|
||||
f.pad(num[1:])
|
||||
}
|
||||
83
vendor/github.com/cockroachdb/redact/internal/hooks.go
generated
vendored
Normal file
83
vendor/github.com/cockroachdb/redact/internal/hooks.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package fmt
|
||||
|
||||
// printArg overrides the original implementation by redirecting the
|
||||
// call to a substitute function in the printer, if available.
|
||||
func (p *pp) printArg(a interface{}, verb rune) {
|
||||
if p.printArgSubstituteFn != nil {
|
||||
p.substituteState = p.printArgSubstituteFn(p, a, verb)
|
||||
} else {
|
||||
p.printArgOrig(a, verb)
|
||||
}
|
||||
}
|
||||
|
||||
// InternalPrinter exposes pp to the redact package.
|
||||
type InternalPrinter = pp
|
||||
|
||||
// InternalBuffer exposes buffer to the redact package.
|
||||
type InternalBuffer = buffer
|
||||
|
||||
// NewInternalPrinter exposes pp allocation to the redact package.
|
||||
func NewInternalPrinter() *InternalPrinter { return newPrinter() }
|
||||
|
||||
// SetHook connects an outer printer to the inner printer.
|
||||
func SetHook(
|
||||
p *InternalPrinter, fn func(p *InternalPrinter, arg interface{}, verb rune) (newState int),
|
||||
) {
|
||||
p.printArgSubstituteFn = fn
|
||||
}
|
||||
|
||||
// Free exposes pp deallocation to the redact package.
|
||||
func Free(p *InternalPrinter) {
|
||||
p.substituteState = 0
|
||||
p.printArgSubstituteFn = nil
|
||||
p.free()
|
||||
}
|
||||
|
||||
// Buf exposes the string buffer to the redact package.
|
||||
func Buf(p *InternalPrinter) []byte { return []byte(p.buf) }
|
||||
|
||||
// GetState exposes the state to the redact package.
|
||||
func GetState(p *InternalPrinter) int {
|
||||
return p.substituteState
|
||||
}
|
||||
|
||||
// SetState exposes the string buffer to the redact package.
|
||||
func SetState(p *InternalPrinter, b []byte) {
|
||||
p.buf = buffer(b)
|
||||
p.substituteState = len(p.buf)
|
||||
}
|
||||
|
||||
// Append adds bytes to the buffer.
|
||||
func Append(p *InternalPrinter, b []byte) { p.buf.write(b) }
|
||||
|
||||
// PrintArg exposes the printArgOrig() method to the redact package.
|
||||
func PrintArg(p *InternalPrinter, a interface{}, verb rune) { p.printArgOrig(a, verb) }
|
||||
|
||||
// DoPrint exposes the doPrint() method to the redact package.
|
||||
func DoPrint(p *InternalPrinter, a []interface{}) { p.doPrint(a) }
|
||||
|
||||
// DoPrintf exposes the doPrintf() method to the redact package.
|
||||
func DoPrintf(p *InternalPrinter, format string, a []interface{}) { p.doPrintf(format, a) }
|
||||
|
||||
// SetCollectError enables wrapped error collection.
|
||||
func SetCollectError(p *InternalPrinter) { p.wrapErrs = true }
|
||||
|
||||
// CollectingError exposes wrapped error collection.
|
||||
func CollectingError(p *InternalPrinter) bool { return p.wrapErrs }
|
||||
|
||||
// WrappedError retrieves the wrapped error if found.
|
||||
func WrappedError(p *InternalPrinter) error { return p.wrappedErr }
|
||||
1189
vendor/github.com/cockroachdb/redact/internal/print.go
generated
vendored
Normal file
1189
vendor/github.com/cockroachdb/redact/internal/print.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
58
vendor/github.com/cockroachdb/redact/internal/print.go.diff
generated
vendored
Normal file
58
vendor/github.com/cockroachdb/redact/internal/print.go.diff
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
--- print.go.orig 2020-08-26 14:49:30.396184000 +0200
|
||||
+++ print.go 2020-08-26 14:50:29.330829000 +0200
|
||||
@@ -1,3 +1,6 @@
|
||||
+// Code generated from print.go.orig. DO NOT EDIT
|
||||
+// GENERATED FILE DO NOT EDIT
|
||||
+//
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
@@ -5,12 +8,16 @@
|
||||
package fmt
|
||||
|
||||
import (
|
||||
- "internal/fmtsort"
|
||||
+ // CUSTOM: needed to avoid a type mismatch on Formatter.
|
||||
+ origFmt "fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"sync"
|
||||
"unicode/utf8"
|
||||
+
|
||||
+ // CUSTOM: our own import since we can't use internal from go stdlib.
|
||||
+ "github.com/cockroachdb/redact/internal/fmtsort"
|
||||
)
|
||||
|
||||
// Strings for use with buffer.WriteString.
|
||||
@@ -51,7 +58,8 @@
|
||||
// The implementation of Format may call Sprint(f) or Fprint(f) etc.
|
||||
// to generate its output.
|
||||
type Formatter interface {
|
||||
- Format(f State, c rune)
|
||||
+ // CUSTOM: refer to the original type, not the one defined here.
|
||||
+ Format(f origFmt.State, c rune)
|
||||
}
|
||||
|
||||
// Stringer is implemented by any value that has a String method,
|
||||
@@ -105,6 +113,10 @@
|
||||
type pp struct {
|
||||
buf buffer
|
||||
|
||||
+ // CUSTOM: hook fn for the redact package.
|
||||
+ printArgSubstituteFn func(p *pp, a interface{}, verb rune) (newState int)
|
||||
+ substituteState int
|
||||
+
|
||||
// arg holds the current item, as an interface{}.
|
||||
arg interface{}
|
||||
|
||||
@@ -635,7 +647,8 @@
|
||||
return false
|
||||
}
|
||||
|
||||
-func (p *pp) printArg(arg interface{}, verb rune) {
|
||||
+// CUSTOM: printArg() renamed to printArgOrig().
|
||||
+func (p *pp) printArgOrig(arg interface{}, verb rune) {
|
||||
p.arg = arg
|
||||
p.value = reflect.Value{}
|
||||
|
||||
29
vendor/github.com/cockroachdb/redact/internal/refresh.sh
generated
vendored
Normal file
29
vendor/github.com/cockroachdb/redact/internal/refresh.sh
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# This file re-generates the sources in this directory from the Go
|
||||
# standard library.
|
||||
#
|
||||
set -euxo pipefail
|
||||
|
||||
(
|
||||
echo "// Code generated from the Go standard library. DO NOT EDIT"
|
||||
echo "// GENERATED FILE DO NOT EDIT"
|
||||
cat $GOROOT/src/fmt/format.go
|
||||
) >format.go
|
||||
|
||||
cp $GOROOT/src/fmt/print.go print.go
|
||||
patch -p0 <print.go.diff
|
||||
|
||||
mkdir -p fmtsort
|
||||
for a in $GOROOT/src/internal/fmtsort/*; do
|
||||
if expr "$a" : ".*_test.go"; then
|
||||
continue
|
||||
fi
|
||||
n=$(basename "$a")
|
||||
(
|
||||
echo "// Code generated from the Go standard library. DO NOT EDIT"
|
||||
echo "// GENERATED FILE DO NOT EDIT"
|
||||
cat "$a"
|
||||
) >fmtsort/"$n"
|
||||
done
|
||||
|
||||
86
vendor/github.com/cockroachdb/redact/make_format.go
generated
vendored
Normal file
86
vendor/github.com/cockroachdb/redact/make_format.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func reproducePrintf(w io.Writer, s fmt.State, verb rune, arg interface{}) {
|
||||
justV, revFmt := MakeFormat(s, verb)
|
||||
if justV {
|
||||
// Common case, avoids generating then parsing the format again.
|
||||
fmt.Fprint(w, arg)
|
||||
} else {
|
||||
fmt.Fprintf(w, revFmt, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// MakeFormat is a helper for use by implementations of the
|
||||
// SafeFormatter interface. It reproduces the format currently active
|
||||
// in fmt.State and verb. This is provided because Go's standard
|
||||
// fmt.State does not make the original format string available to us.
|
||||
//
|
||||
// If the return value justV is true, then the current state
|
||||
// was found to be %v exactly; in that case the caller
|
||||
// can avoid a full-blown Printf call and use just Print instead
|
||||
// to take a shortcut.
|
||||
func MakeFormat(s fmt.State, verb rune) (justV bool, format string) {
|
||||
plus, minus, hash, sp, z := s.Flag('+'), s.Flag('-'), s.Flag('#'), s.Flag(' '), s.Flag('0')
|
||||
w, wp := s.Width()
|
||||
p, pp := s.Precision()
|
||||
|
||||
if !plus && !minus && !hash && !sp && !z && !wp && !pp {
|
||||
switch verb {
|
||||
case 'v':
|
||||
return true, "%v"
|
||||
case 's':
|
||||
return false, "%s"
|
||||
case 'd':
|
||||
return false, "%d"
|
||||
}
|
||||
// Other cases handled in the slow path below.
|
||||
}
|
||||
|
||||
var f strings.Builder
|
||||
f.WriteByte('%')
|
||||
if plus {
|
||||
f.WriteByte('+')
|
||||
}
|
||||
if minus {
|
||||
f.WriteByte('-')
|
||||
}
|
||||
if hash {
|
||||
f.WriteByte('#')
|
||||
}
|
||||
if sp {
|
||||
f.WriteByte(' ')
|
||||
}
|
||||
if z {
|
||||
f.WriteByte('0')
|
||||
}
|
||||
if wp {
|
||||
f.WriteString(strconv.Itoa(w))
|
||||
}
|
||||
if pp {
|
||||
f.WriteByte('.')
|
||||
f.WriteString(strconv.Itoa(p))
|
||||
}
|
||||
f.WriteRune(verb)
|
||||
return false, f.String()
|
||||
}
|
||||
109
vendor/github.com/cockroachdb/redact/markers.go
generated
vendored
Normal file
109
vendor/github.com/cockroachdb/redact/markers.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import "bytes"
|
||||
|
||||
// RedactableString is a string that contains a mix of safe and unsafe
|
||||
// bits of data, but where it is known that unsafe bits are enclosed
|
||||
// by redaction markers ‹ and ›, and occurrences of the markers
|
||||
// inside the original data items have been escaped.
|
||||
//
|
||||
// Instances of RedactableString should not be constructed directly;
|
||||
// instead use the facilities from print.go (Sprint, Sprintf)
|
||||
// or the methods below.
|
||||
type RedactableString string
|
||||
|
||||
// StripMarkers removes the redaction markers from the
|
||||
// RedactableString. This returns an unsafe string where all safe and
|
||||
// unsafe bits are mixed together.
|
||||
func (s RedactableString) StripMarkers() string {
|
||||
return reStripMarkers.ReplaceAllString(string(s), "")
|
||||
}
|
||||
|
||||
// Redact replaces all occurrences of unsafe substrings by the
|
||||
// “Redacted” marker, ‹×›. The result string is still safe.
|
||||
func (s RedactableString) Redact() RedactableString {
|
||||
return RedactableString(reStripSensitive.ReplaceAllString(string(s), redactedS))
|
||||
}
|
||||
|
||||
// ToBytes converts the string to a byte slice.
|
||||
func (s RedactableString) ToBytes() RedactableBytes {
|
||||
return RedactableBytes([]byte(string(s)))
|
||||
}
|
||||
|
||||
// SafeFormat formats the redactable safely.
|
||||
func (s RedactableString) SafeFormat(sp SafePrinter, _ rune) {
|
||||
// As per annotateArgs() in markers_internal_print.go,
|
||||
// we consider the redactable string not further formattable.
|
||||
sp.Print(s)
|
||||
}
|
||||
|
||||
// RedactableBytes is like RedactableString but is a byte slice.
|
||||
//
|
||||
// Instances of RedactableBytes should not be constructed directly;
|
||||
// instead use the facilities from print.go (Sprint, Sprintf)
|
||||
// or the methods below.
|
||||
type RedactableBytes []byte
|
||||
|
||||
// StripMarkers removes the redaction markers from the
|
||||
// RedactableBytes. This returns an unsafe string where all safe and
|
||||
// unsafe bits are mixed together.
|
||||
func (s RedactableBytes) StripMarkers() []byte {
|
||||
return reStripMarkers.ReplaceAll([]byte(s), nil)
|
||||
}
|
||||
|
||||
// Redact replaces all occurrences of unsafe substrings by the
|
||||
// “Redacted” marker, ‹×›.
|
||||
func (s RedactableBytes) Redact() RedactableBytes {
|
||||
return RedactableBytes(reStripSensitive.ReplaceAll(s, redactedBytes))
|
||||
}
|
||||
|
||||
// ToString converts the byte slice to a string.
|
||||
func (s RedactableBytes) ToString() RedactableString {
|
||||
return RedactableString(string([]byte(s)))
|
||||
}
|
||||
|
||||
// SafeFormat formats the redactable safely.
|
||||
func (s RedactableBytes) SafeFormat(sp SafePrinter, _ rune) {
|
||||
// As per annotateArgs() in markers_internal_print.go,
|
||||
// we consider the redactable bytes not further formattable.
|
||||
sp.Print(s)
|
||||
}
|
||||
|
||||
// EscapeBytes escapes markers inside the given byte slice and encloses
|
||||
// the entire byte slice between redaction markers.
|
||||
func EscapeBytes(s []byte) RedactableBytes {
|
||||
var buf bytes.Buffer
|
||||
buf.Grow(len(s) + len(startRedactableS) + len(endRedactableS))
|
||||
e := escapeWriter{w: &buf, enclose: true, strip: false}
|
||||
_, _ = e.Write(s)
|
||||
return RedactableBytes(buf.Bytes())
|
||||
}
|
||||
|
||||
// StartMarker returns the start delimiter for an unsafe string.
|
||||
func StartMarker() []byte { return startRedactableBytes }
|
||||
|
||||
// EndMarker returns the end delimiter for an unsafe string.
|
||||
func EndMarker() []byte { return endRedactableBytes }
|
||||
|
||||
// RedactedMarker returns the special string used by Redact.
|
||||
func RedactedMarker() []byte { return redactedBytes }
|
||||
|
||||
// EscapeMarkers escapes the special delimiters from the provided
|
||||
// byte slice.
|
||||
func EscapeMarkers(s []byte) []byte {
|
||||
return reStripMarkers.ReplaceAll(s, escapeBytes)
|
||||
}
|
||||
40
vendor/github.com/cockroachdb/redact/markers_internal_constants.go
generated
vendored
Normal file
40
vendor/github.com/cockroachdb/redact/markers_internal_constants.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import "regexp"
|
||||
|
||||
const startRedactable = '‹'
|
||||
const startRedactableS = string(startRedactable)
|
||||
|
||||
var startRedactableBytes = []byte(startRedactableS)
|
||||
|
||||
const endRedactable = '›'
|
||||
const endRedactableS = string(endRedactable)
|
||||
|
||||
var endRedactableBytes = []byte(endRedactableS)
|
||||
|
||||
const escapeMark = '?'
|
||||
const escapeMarkS = string(escapeMark)
|
||||
|
||||
var escapeBytes = []byte(escapeMarkS)
|
||||
|
||||
const redactedS = startRedactableS + "×" + endRedactableS
|
||||
|
||||
var redactedBytes = []byte(redactedS)
|
||||
|
||||
var reStripSensitive = regexp.MustCompile(startRedactableS + "[^" + startRedactableS + endRedactableS + "]*" + endRedactableS)
|
||||
|
||||
var reStripMarkers = regexp.MustCompile("[" + startRedactableS + endRedactableS + "]")
|
||||
217
vendor/github.com/cockroachdb/redact/markers_internal_escape.go
generated
vendored
Normal file
217
vendor/github.com/cockroachdb/redact/markers_internal_escape.go
generated
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// escapeState abstracts on top of fmt.State and ensures that call
|
||||
// calls to Write() enclose the writtne bytes between unsafe markers.
|
||||
type escapeState struct {
|
||||
fmt.State
|
||||
w escapeWriter
|
||||
}
|
||||
|
||||
var _ fmt.State = (*escapeState)(nil)
|
||||
|
||||
func makeEscapeState(s fmt.State, buf *bytes.Buffer) escapeState {
|
||||
e := escapeState{State: s}
|
||||
e.w = escapeWriter{w: buf, enclose: true}
|
||||
return e
|
||||
}
|
||||
|
||||
// Write is part of the fmt.State interface and implements the io.Writer interface.
|
||||
func (p *escapeState) Write(b []byte) (int, error) {
|
||||
return p.w.Write(b)
|
||||
}
|
||||
|
||||
// escapeWriter abstracts on top of io.Writer and ensures that all
|
||||
// calls to Write() escape markers.
|
||||
// Also, final spaces and newlines are stripped if strip is set.
|
||||
// Also, the overall result is enclosed inside redaction markers
|
||||
// if enclose is true.
|
||||
type escapeWriter struct {
|
||||
w io.Writer
|
||||
enclose bool
|
||||
strip bool
|
||||
}
|
||||
|
||||
var _ io.Writer = (*escapeWriter)(nil)
|
||||
|
||||
// Write implements the io.Writer interface.
|
||||
func (p *escapeWriter) Write(b []byte) (int, error) {
|
||||
st := escapeResult{0, nil}
|
||||
|
||||
if p.strip {
|
||||
// Trim final newlines/spaces, for convenience.
|
||||
end := len(b)
|
||||
for i := end - 1; i >= 0; i-- {
|
||||
if b[i] == '\n' || b[i] == ' ' {
|
||||
end = i
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
b = b[:end]
|
||||
}
|
||||
|
||||
// Here we could choose to omit the output
|
||||
// entirely if there was nothing but empty space:
|
||||
// if len(b) == 0 { return 0, nil }
|
||||
|
||||
// Note: we use len(...RedactableS) and not len(...RedactableBytes)
|
||||
// because the ...S variant is a compile-time constant so this
|
||||
// accelerates the loops below.
|
||||
start, ls := startRedactableBytes, len(startRedactableS)
|
||||
end, le := endRedactableBytes, len(endRedactableS)
|
||||
escape := escapeBytes
|
||||
|
||||
if p.enclose {
|
||||
st = p.doWrite(start, st, false)
|
||||
}
|
||||
|
||||
// Now write the string.
|
||||
|
||||
// k is the index in b up to (and excluding) the byte which we've
|
||||
// already copied into the output.
|
||||
k := 0
|
||||
|
||||
for i := 0; i < len(b); i++ {
|
||||
if b[i] == '\n' && p.enclose {
|
||||
// Avoid enclosing newline characters inside redaction markers.
|
||||
// This is important when redact is used to render errors, where
|
||||
// sub-strings split at newline characters are rendered
|
||||
// separately.
|
||||
st = p.doWrite(b[k:i], st, true)
|
||||
st = p.doWrite(end, st, false)
|
||||
// Advance to the last newline character. We want to forward
|
||||
// them all in a single call to doWrite, for performance.
|
||||
lastNewLine := i
|
||||
for b[lastNewLine] == '\n' && lastNewLine < len(b) {
|
||||
lastNewLine++
|
||||
}
|
||||
st = p.doWrite(b[i:lastNewLine], st, true)
|
||||
st = p.doWrite(start, st, false)
|
||||
// Advance the counters by the number of newline characters.
|
||||
k = lastNewLine
|
||||
i = lastNewLine - 1 /* -1 because we have i++ at the end of every iteration */
|
||||
} else {
|
||||
// Ensure that occurrences of the delimiter inside the string get
|
||||
// escaped.
|
||||
// Reminder: ls and le are likely greater than 1, as we are scanning
|
||||
// utf-8 encoded delimiters (the utf-8 encoding is multibyte).
|
||||
if i+ls <= len(b) && bytes.Equal(b[i:i+ls], start) {
|
||||
st = p.doWrite(b[k:i], st, true)
|
||||
st = p.doWrite(escape, st, false)
|
||||
// Advance the counters by the length (in bytes) of the delimiter.
|
||||
st.l += ls
|
||||
k = i + ls
|
||||
i += ls - 1 /* -1 because we have i++ at the end of every iteration */
|
||||
} else if i+le <= len(b) && bytes.Equal(b[i:i+le], end) {
|
||||
st = p.doWrite(b[k:i], st, true)
|
||||
st = p.doWrite(escape, st, false)
|
||||
// Advance the counters by the length (in bytes) of the delimiter.
|
||||
st.l += le
|
||||
k = i + le
|
||||
i += le - 1 /* -1 because we have i++ at the end of every iteration */
|
||||
}
|
||||
}
|
||||
}
|
||||
st = p.doWrite(b[k:], st, true)
|
||||
if p.enclose {
|
||||
st = p.doWrite(end, st, false)
|
||||
}
|
||||
return st.l, st.err
|
||||
}
|
||||
|
||||
type escapeResult struct {
|
||||
l int
|
||||
err error
|
||||
}
|
||||
|
||||
func (p *escapeWriter) doWrite(b []byte, st escapeResult, count bool) escapeResult {
|
||||
if st.err != nil {
|
||||
// An error was encountered previously.
|
||||
// No-op.
|
||||
return st
|
||||
}
|
||||
sz, err := p.w.Write(b)
|
||||
if count {
|
||||
st.l += sz
|
||||
}
|
||||
st.err = err
|
||||
return st
|
||||
}
|
||||
|
||||
// internalEscapeBytes escapes redaction markers in the provided buf
|
||||
// starting at the location startLoc.
|
||||
// The bytes before startLoc are considered safe (already escaped).
|
||||
func internalEscapeBytes(b []byte, startLoc int) (res []byte) {
|
||||
// Note: we use len(...RedactableS) and not len(...RedactableBytes)
|
||||
// because the ...S variant is a compile-time constant so this
|
||||
// accelerates the loops below.
|
||||
start, ls := startRedactableBytes, len(startRedactableS)
|
||||
end, le := endRedactableBytes, len(endRedactableS)
|
||||
escape := escapeBytes
|
||||
|
||||
// res is the output slice. In the common case where there is
|
||||
// nothing to escape, the input slice is returned directly
|
||||
// and no allocation takes place.
|
||||
res = b
|
||||
// copied is true if and only if `res` is a copy of `b`. It only
|
||||
// turns to true if the loop below finds something to escape.
|
||||
copied := false
|
||||
// k is the index in b up to (and excluding) the byte which we've
|
||||
// already copied into res (if copied=true).
|
||||
k := 0
|
||||
|
||||
for i := startLoc; i < len(b); i++ {
|
||||
// Ensure that occurrences of the delimiter inside the string get
|
||||
// escaped.
|
||||
// Reminder: ls and le are likely greater than 1, as we are scanning
|
||||
// utf-8 encoded delimiters (the utf-8 encoding is multibyte).
|
||||
if i+ls <= len(b) && bytes.Equal(b[i:i+ls], start) {
|
||||
if !copied {
|
||||
// We only allocate an output slice when we know we definitely
|
||||
// need it.
|
||||
res = make([]byte, 0, len(b)+len(escape))
|
||||
copied = true
|
||||
}
|
||||
res = append(res, b[k:i]...)
|
||||
res = append(res, escape...)
|
||||
// Advance the counters by the length (in bytes) of the delimiter.
|
||||
k = i + ls
|
||||
i += ls - 1 /* -1 because we have i++ at the end of every iteration */
|
||||
} else if i+le <= len(b) && bytes.Equal(b[i:i+le], end) {
|
||||
if !copied {
|
||||
// See the comment above about res allocation.
|
||||
res = make([]byte, 0, len(b)+len(escape))
|
||||
copied = true
|
||||
}
|
||||
res = append(res, b[k:i]...)
|
||||
res = append(res, escape...)
|
||||
// Advance the counters by the length (in bytes) of the delimiter.
|
||||
k = i + le
|
||||
i += le - 1 /* -1 because we have i++ at the end of every iteration */
|
||||
}
|
||||
}
|
||||
if copied {
|
||||
res = append(res, b[k:]...)
|
||||
}
|
||||
return
|
||||
}
|
||||
264
vendor/github.com/cockroachdb/redact/markers_internal_print.go
generated
vendored
Normal file
264
vendor/github.com/cockroachdb/redact/markers_internal_print.go
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
internalFmt "github.com/cockroachdb/redact/internal"
|
||||
)
|
||||
|
||||
// printArgFn is the hook injected into the standard fmt logic
|
||||
// by the printer functions in markers_print.go.
|
||||
func printArgFn(p *internalFmt.InternalPrinter, arg interface{}, verb rune) (newState int) {
|
||||
redactLastWrites(p)
|
||||
|
||||
switch verb {
|
||||
case 'T':
|
||||
// If the value was wrapped, reveal its original type. Anything else is not very useful.
|
||||
switch v := arg.(type) {
|
||||
case safeWrapper:
|
||||
arg = v.a
|
||||
case unsafeWrap:
|
||||
arg = v.a
|
||||
}
|
||||
|
||||
// Shortcut: %T is always safe to print as-is.
|
||||
internalFmt.PrintArg(p, arg, verb)
|
||||
return len(internalFmt.Buf(p))
|
||||
case 'p':
|
||||
// Printing a pointer via %p is handled as special case in printf,
|
||||
// so we need a special case here too. The other cases of
|
||||
// printing a pointer via %v / %d %x etc is handled by the common path.
|
||||
|
||||
switch v := arg.(type) {
|
||||
case safeWrapper:
|
||||
// If the value was meant to be safe, then print it as-is.
|
||||
internalFmt.PrintArg(p, v.a, verb)
|
||||
return len(internalFmt.Buf(p))
|
||||
|
||||
case unsafeWrap:
|
||||
// If it's been wrapped, unwrap it. This helps preserve the
|
||||
// original pointer value in the output.
|
||||
arg = v.a
|
||||
}
|
||||
// Now perform an unsafe print: we are assuming that the pointer
|
||||
// representation by the fmt.printf code does not contain
|
||||
// redaction markers, and go a short route. If that assumption did
|
||||
// not hold (or is invalidated by changes upstream after this
|
||||
// comment is written), this code should be changed to use the
|
||||
// escapeWriter instead.
|
||||
internalFmt.Append(p, startRedactableBytes)
|
||||
internalFmt.PrintArg(p, arg, verb)
|
||||
internalFmt.Append(p, endRedactableBytes)
|
||||
return len(internalFmt.Buf(p))
|
||||
}
|
||||
|
||||
// nil arguments are printed as-is. Note: a nil argument under
|
||||
// interface{} is not the same as a nil pointer passed via a pointer
|
||||
// of a concrete type. The latter kind of nil goes through
|
||||
// redaction as usual, because it may have its own custom Format() method.
|
||||
if arg == nil {
|
||||
internalFmt.PrintArg(p, arg, verb)
|
||||
return len(internalFmt.Buf(p))
|
||||
}
|
||||
|
||||
// RedactableBytes/RedactableString are already formatted as
|
||||
// redactable. Include them as-is.
|
||||
//
|
||||
// NB: keep this logic synchronized with
|
||||
// (RedactableString/Bytes).SafeFormat().
|
||||
switch v := arg.(type) {
|
||||
case RedactableString:
|
||||
internalFmt.Append(p, []byte(v))
|
||||
return len(internalFmt.Buf(p))
|
||||
case RedactableBytes:
|
||||
internalFmt.Append(p, []byte(v))
|
||||
return len(internalFmt.Buf(p))
|
||||
}
|
||||
|
||||
arg = annotateArg(arg, internalFmt.CollectingError(p))
|
||||
internalFmt.PrintArg(p, arg, verb)
|
||||
return len(internalFmt.Buf(p))
|
||||
}
|
||||
|
||||
// redactLastWrites escapes any markers that were added by the
|
||||
// internals of the printf functions, for example
|
||||
// if markers were present in the format string.
|
||||
func redactLastWrites(p *internalFmt.InternalPrinter) {
|
||||
state := internalFmt.GetState(p)
|
||||
newBuf := internalEscapeBytes(internalFmt.Buf(p), state)
|
||||
internalFmt.SetState(p, newBuf)
|
||||
}
|
||||
|
||||
// annotateArg wraps the arguments to one of the print functions with
|
||||
// an indirect formatter which ensures that redaction markers inside
|
||||
// the representation of the object are escaped, and optionally
|
||||
// encloses the result of the display between redaction markers.
|
||||
//
|
||||
// collectingError is true iff we are in the context of
|
||||
// HelperForErrorf, where we want the %w verb to work properly. This
|
||||
// adds a little overhead to the processing, but this is OK because
|
||||
// typically the error path is not perf-critical.
|
||||
func annotateArg(arg interface{}, collectingError bool) interface{} {
|
||||
var newArg fmt.Formatter
|
||||
err, isError := arg.(error)
|
||||
|
||||
switch v := arg.(type) {
|
||||
case SafeFormatter:
|
||||
// calls to Format() by fmt.Print will be redirected to
|
||||
// v.SafeFormat(). This delegates the task of adding markers to
|
||||
// the object itself.
|
||||
newArg = &redactFormatRedirect{
|
||||
func(p SafePrinter, verb rune) { v.SafeFormat(p, verb) },
|
||||
}
|
||||
|
||||
case SafeValue:
|
||||
// calls to Format() by fmt.Print will be redirected to a
|
||||
// display of v without redaction markers.
|
||||
//
|
||||
// Note that we can't let the value be displayed as-is because
|
||||
// we must prevent any marker inside the value from leaking into
|
||||
// the result. (We want to avoid mismatched markers.)
|
||||
newArg = &escapeArg{arg: arg, enclose: false}
|
||||
|
||||
case SafeMessager:
|
||||
// Obsolete interface.
|
||||
// TODO(knz): Remove this.
|
||||
newArg = &escapeArg{arg: v.SafeMessage(), enclose: false}
|
||||
|
||||
default:
|
||||
if isError && redactErrorFn != nil {
|
||||
// We place this case after the other cases above, in case
|
||||
// the error object knows how to print itself safely already.
|
||||
newArg = &redactFormatRedirect{
|
||||
func(p SafePrinter, verb rune) { redactErrorFn(err, p, verb) },
|
||||
}
|
||||
} else {
|
||||
// calls to Format() by fmt.Print will be redirected to a
|
||||
// display of v within redaction markers if the type is
|
||||
// considered unsafe, without markers otherwise. In any case,
|
||||
// occurrences of delimiters within are escaped.
|
||||
newArg = &escapeArg{arg: v, enclose: !isSafeValue(v)}
|
||||
}
|
||||
}
|
||||
|
||||
if isError && collectingError {
|
||||
// Ensure the arg still implements the `error` interface for
|
||||
// detection by the handling of %w, while also implementing
|
||||
// fmt.Formatter to forward the implementation to the objects
|
||||
// constructed above.
|
||||
newArg = &makeError{err: err, arg: newArg}
|
||||
}
|
||||
|
||||
return newArg
|
||||
}
|
||||
|
||||
type makeError struct {
|
||||
err error
|
||||
arg fmt.Formatter
|
||||
}
|
||||
|
||||
// Error implements error.
|
||||
func (m *makeError) Error() string { return m.err.Error() }
|
||||
|
||||
// Format implements fmt.Formatter.
|
||||
func (m *makeError) Format(f fmt.State, verb rune) { m.arg.Format(f, verb) }
|
||||
|
||||
// redactFormatRedirect wraps a safe print callback and uses it to
|
||||
// implement fmt.Formatter.
|
||||
type redactFormatRedirect struct {
|
||||
printFn func(p SafePrinter, verb rune)
|
||||
}
|
||||
|
||||
// Format implements fmt.Formatter.
|
||||
func (r *redactFormatRedirect) Format(s fmt.State, verb rune) {
|
||||
defer func() {
|
||||
if p := recover(); p != nil {
|
||||
e := escapeWriter{w: s}
|
||||
fmt.Fprintf(&e, "%%!%c(PANIC=SafeFormatter method: %v)", verb, p)
|
||||
}
|
||||
}()
|
||||
p := &printer{}
|
||||
p.escapeState = makeEscapeState(s, &p.buf)
|
||||
r.printFn(p, verb)
|
||||
_, _ = s.Write(p.buf.Bytes())
|
||||
}
|
||||
|
||||
// passthrough passes a pre-formatted string through.
|
||||
type passthrough struct{ arg []byte }
|
||||
|
||||
// Format implements fmt.Formatter.
|
||||
func (p *passthrough) Format(s fmt.State, _ rune) {
|
||||
_, _ = s.Write(p.arg)
|
||||
}
|
||||
|
||||
// escapeArg wraps an arbitrary value and ensures that any occurrence
|
||||
// of the redaction markers in its representation are escaped.
|
||||
//
|
||||
// The result of printing out the value is enclosed within markers or
|
||||
// not depending on the value of the enclose bool.
|
||||
type escapeArg struct {
|
||||
arg interface{}
|
||||
enclose bool
|
||||
}
|
||||
|
||||
func (r *escapeArg) Format(s fmt.State, verb rune) {
|
||||
switch t := r.arg.(type) {
|
||||
case fmt.Formatter:
|
||||
// This is a special case from the default case below, which
|
||||
// allows a shortcut through the layers of the fmt package.
|
||||
p := &escapeState{
|
||||
State: s,
|
||||
w: escapeWriter{
|
||||
w: s,
|
||||
enclose: r.enclose,
|
||||
strip: r.enclose,
|
||||
}}
|
||||
defer func() {
|
||||
if recovered := recover(); recovered != nil {
|
||||
fmt.Fprintf(p, "%%!%c(PANIC=Format method: %v)", verb, recovered)
|
||||
}
|
||||
}()
|
||||
t.Format(p, verb)
|
||||
|
||||
default:
|
||||
// TODO(knz): It would be possible to implement struct formatting
|
||||
// with conditional redaction based on field tag annotations here.
|
||||
p := &escapeWriter{w: s, enclose: r.enclose, strip: r.enclose}
|
||||
reproducePrintf(p, s, verb, r.arg)
|
||||
}
|
||||
}
|
||||
|
||||
// printerfn is a helper struct for use by Sprintfn.
|
||||
type printerfn struct {
|
||||
fn func(SafePrinter)
|
||||
}
|
||||
|
||||
// SafeFormat implements the SafeFormatter interface.
|
||||
func (p printerfn) SafeFormat(w SafePrinter, _ rune) {
|
||||
p.fn(w)
|
||||
}
|
||||
|
||||
// redactErrorFn can be injected from an error library
|
||||
// to render error objects safely.
|
||||
var redactErrorFn func(err error, p SafePrinter, verb rune)
|
||||
|
||||
// RegisterRedactErrorFn registers an error redaction function for use
|
||||
// during automatic redaction by this package.
|
||||
// Provided e.g. by cockroachdb/errors.
|
||||
func RegisterRedactErrorFn(fn func(err error, p SafePrinter, verb rune)) {
|
||||
redactErrorFn = fn
|
||||
}
|
||||
88
vendor/github.com/cockroachdb/redact/markers_internal_printer.go
generated
vendored
Normal file
88
vendor/github.com/cockroachdb/redact/markers_internal_printer.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// printer implements SafePrinter.
|
||||
// This is the machinery for the Print() functions offered
|
||||
// by this package.
|
||||
type printer struct {
|
||||
escapeState
|
||||
buf bytes.Buffer
|
||||
}
|
||||
|
||||
var _ fmt.State = (*printer)(nil)
|
||||
var _ SafeWriter = (*printer)(nil)
|
||||
|
||||
// Print is part of the SafeWriter interface.
|
||||
func (b *printer) Print(args ...interface{}) {
|
||||
_, _ = Fprint(&b.buf, args...)
|
||||
}
|
||||
|
||||
// Printf is part of the SafeWriter interface.
|
||||
func (b *printer) Printf(format string, args ...interface{}) {
|
||||
_, _ = Fprintf(&b.buf, format, args...)
|
||||
}
|
||||
|
||||
// SafeString is part of the SafeWriter interface.
|
||||
func (b *printer) SafeString(s SafeString) {
|
||||
w := escapeWriter{w: &b.buf, enclose: false}
|
||||
_, _ = w.Write([]byte(s))
|
||||
}
|
||||
|
||||
// SafeRune is part of the SafeWriter interface.
|
||||
func (b *printer) SafeRune(s SafeRune) {
|
||||
if s == startRedactable || s == endRedactable {
|
||||
s = escapeMark
|
||||
}
|
||||
_, _ = b.buf.WriteRune(rune(s))
|
||||
}
|
||||
|
||||
// UnsafeString is part of the SafeWriter interface.
|
||||
func (b *printer) UnsafeString(s string) {
|
||||
w := escapeWriter{w: &b.buf, enclose: true, strip: true}
|
||||
_, _ = w.Write([]byte(s))
|
||||
}
|
||||
|
||||
// UnsafeRune is part of the SafeWriter interface.
|
||||
func (b *printer) UnsafeRune(s rune) {
|
||||
_, _ = b.buf.WriteRune(startRedactable)
|
||||
b.SafeRune(SafeRune(s))
|
||||
_, _ = b.buf.WriteRune(endRedactable)
|
||||
}
|
||||
|
||||
// UnsafeByte is part of the SafeWriter interface.
|
||||
func (b *printer) UnsafeByte(s byte) {
|
||||
_, _ = b.buf.WriteRune(startRedactable)
|
||||
if s >= utf8.RuneSelf ||
|
||||
s == startRedactableBytes[0] || s == endRedactableBytes[0] {
|
||||
// Unsafe byte. Escape it.
|
||||
_, _ = b.buf.Write(escapeBytes)
|
||||
} else {
|
||||
_ = b.buf.WriteByte(s)
|
||||
}
|
||||
_, _ = b.buf.WriteRune(endRedactable)
|
||||
}
|
||||
|
||||
// UnsafeBytes is part of the SafeWriter interface.
|
||||
func (b *printer) UnsafeBytes(s []byte) {
|
||||
w := escapeWriter{w: &b.buf, enclose: true, strip: true}
|
||||
_, _ = w.Write(s)
|
||||
}
|
||||
31
vendor/github.com/cockroachdb/redact/markers_internal_types.go
generated
vendored
Normal file
31
vendor/github.com/cockroachdb/redact/markers_internal_types.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import "reflect"
|
||||
|
||||
// RegisterSafeType registers a data type to always be considered safe
|
||||
// during the production of redactable strings.
|
||||
func RegisterSafeType(t reflect.Type) {
|
||||
safeTypeRegistry[t] = true
|
||||
}
|
||||
|
||||
// safeTypeRegistry registers Go data types that are to be always
|
||||
// considered safe, even when they don't implement SafeValue.
|
||||
var safeTypeRegistry = map[reflect.Type]bool{}
|
||||
|
||||
func isSafeValue(a interface{}) bool {
|
||||
return safeTypeRegistry[reflect.TypeOf(a)]
|
||||
}
|
||||
122
vendor/github.com/cockroachdb/redact/markers_print.go
generated
vendored
Normal file
122
vendor/github.com/cockroachdb/redact/markers_print.go
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
internalFmt "github.com/cockroachdb/redact/internal"
|
||||
)
|
||||
|
||||
// Sprint prints out the arguments and encloses unsafe bits
|
||||
// between redaction markers.
|
||||
// If either safe and unsafe bits of data contain the markers
|
||||
// in their representation already, they are escaped first.
|
||||
// If a RedactableString or RedactableBytes argument is passed,
|
||||
// it is reproduced as-is without escaping.
|
||||
func Sprint(args ...interface{}) RedactableString {
|
||||
p := internalFmt.NewInternalPrinter()
|
||||
internalFmt.SetHook(p, printArgFn)
|
||||
internalFmt.DoPrint(p, args)
|
||||
redactLastWrites(p)
|
||||
s := RedactableString(internalFmt.Buf(p))
|
||||
internalFmt.Free(p)
|
||||
return s
|
||||
}
|
||||
|
||||
// Sprintf formats the arguments and encloses unsafe bits
|
||||
// between redaction markers.
|
||||
// If either safe and unsafe bits of data contain the markers
|
||||
// in their representation already, they are escaped first.
|
||||
// The format is always considered safe and the caller
|
||||
// is responsible to ensure that the markers are not present
|
||||
// in the format string.
|
||||
func Sprintf(format string, args ...interface{}) RedactableString {
|
||||
p := internalFmt.NewInternalPrinter()
|
||||
internalFmt.SetHook(p, printArgFn)
|
||||
internalFmt.DoPrintf(p, format, args)
|
||||
redactLastWrites(p)
|
||||
s := RedactableString(internalFmt.Buf(p))
|
||||
internalFmt.Free(p)
|
||||
return s
|
||||
}
|
||||
|
||||
// HelperForErrorf is a helper to implement a redaction-aware
|
||||
// fmt.Errorf-compatible function in a different package. It formats
|
||||
// the string according to the given format and arguments in the same
|
||||
// way as Sprintf, but in addition to this if the format contains %w
|
||||
// and an error object in the proper argument position it also returns
|
||||
// that error object.
|
||||
//
|
||||
// Note: This function only works if an error redaction function
|
||||
// has been injected with RegisterRedactErrorFn().
|
||||
func HelperForErrorf(format string, args ...interface{}) (RedactableString, error) {
|
||||
p := internalFmt.NewInternalPrinter()
|
||||
internalFmt.SetCollectError(p)
|
||||
internalFmt.SetHook(p, printArgFn)
|
||||
internalFmt.DoPrintf(p, format, args)
|
||||
redactLastWrites(p)
|
||||
s := RedactableString(internalFmt.Buf(p))
|
||||
e := internalFmt.WrappedError(p)
|
||||
internalFmt.Free(p)
|
||||
if m, ok := e.(*makeError); ok {
|
||||
e = m.err
|
||||
}
|
||||
return s, e
|
||||
}
|
||||
|
||||
// Sprintfn produces a RedactableString using the provided
|
||||
// SafeFormat-alike function.
|
||||
func Sprintfn(printer func(w SafePrinter)) RedactableString {
|
||||
return Sprint(printerfn{printer})
|
||||
}
|
||||
|
||||
// StringWithoutMarkers formats the provided SafeFormatter and strips
|
||||
// the redaction markers from the result. This is provided for
|
||||
// convenience to facilitate the implementation of String() methods
|
||||
// alongside SafeFormat() to avoid code duplication.
|
||||
//
|
||||
// Note: if this function is ever found to be a performance
|
||||
// bottleneck, one can consider using an alternate implementation of
|
||||
// Sprint() which similarly calls the SafeFormat() methods but does
|
||||
// not introduce markers and instead writes to a string buffer
|
||||
// directly.
|
||||
func StringWithoutMarkers(f SafeFormatter) string {
|
||||
return Sprint(f).StripMarkers()
|
||||
}
|
||||
|
||||
// Fprint is like Sprint but outputs the redactable
|
||||
// string to the provided Writer.
|
||||
func Fprint(w io.Writer, args ...interface{}) (n int, err error) {
|
||||
p := internalFmt.NewInternalPrinter()
|
||||
internalFmt.SetHook(p, printArgFn)
|
||||
internalFmt.DoPrint(p, args)
|
||||
redactLastWrites(p)
|
||||
n, err = w.Write(internalFmt.Buf(p))
|
||||
internalFmt.Free(p)
|
||||
return
|
||||
}
|
||||
|
||||
// Fprintf is like Sprintf but outputs the redactable string to the
|
||||
// provided Writer.
|
||||
func Fprintf(w io.Writer, format string, args ...interface{}) (n int, err error) {
|
||||
p := internalFmt.NewInternalPrinter()
|
||||
internalFmt.SetHook(p, printArgFn)
|
||||
internalFmt.DoPrintf(p, format, args)
|
||||
redactLastWrites(p)
|
||||
n, err = w.Write(internalFmt.Buf(p))
|
||||
internalFmt.Free(p)
|
||||
return
|
||||
}
|
||||
63
vendor/github.com/cockroachdb/redact/wrappers.go
generated
vendored
Normal file
63
vendor/github.com/cockroachdb/redact/wrappers.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2020 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package redact
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Unsafe turns any value that would otherwise be considered safe,
|
||||
// into an unsafe value.
|
||||
func Unsafe(a interface{}) interface{} {
|
||||
return unsafeWrap{a}
|
||||
}
|
||||
|
||||
type unsafeWrap struct {
|
||||
a interface{}
|
||||
}
|
||||
|
||||
func (w unsafeWrap) Format(s fmt.State, verb rune) {
|
||||
reproducePrintf(s, s, verb, w.a)
|
||||
}
|
||||
|
||||
// Safe turns any value into an object that is considered as safe by
|
||||
// the formatter.
|
||||
//
|
||||
// This is provided as an “escape hatch” for cases where the other
|
||||
// interfaces and conventions fail. Increased usage of this mechanism
|
||||
// should be taken as a signal that a new abstraction is missing.
|
||||
// The implementation is also slow.
|
||||
func Safe(a interface{}) SafeValue {
|
||||
return safeWrapper{a}
|
||||
}
|
||||
|
||||
type safeWrapper struct {
|
||||
a interface{}
|
||||
}
|
||||
|
||||
var _ SafeValue = safeWrapper{}
|
||||
var _ fmt.Formatter = safeWrapper{}
|
||||
var _ SafeMessager = safeWrapper{}
|
||||
|
||||
// SafeValue implements the SafeValue interface.
|
||||
func (w safeWrapper) SafeValue() {}
|
||||
|
||||
// Format implements the fmt.Formatter interface.
|
||||
func (w safeWrapper) Format(s fmt.State, verb rune) {
|
||||
reproducePrintf(s, s, verb, w.a)
|
||||
}
|
||||
|
||||
// SafeMessage implements SafeMessager.
|
||||
func (w safeWrapper) SafeMessage() string {
|
||||
return fmt.Sprintf("%v", w.a)
|
||||
}
|
||||
Reference in New Issue
Block a user