Skip to content

Commit

Permalink
Merge pull request #22 from knz/20210625-safe-nums
Browse files Browse the repository at this point in the history
New APIs for safe numeric values
  • Loading branch information
knz committed Jun 25, 2021
2 parents 7824382 + 66549ca commit 2c44c49
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 12 deletions.
15 changes: 10 additions & 5 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,18 @@ type SafePrinter = i.SafePrinter
// SafeFormatter, to format mixes of safe and unsafe strings.
type SafeWriter = i.SafeWriter

// 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.
// SafeString represents a string that is not a sensitive value.
type SafeString = i.SafeString

// SafeInt represents an integer that is not a sensitive value.
type SafeInt = i.SafeInt

// SafeUint represents an integer that is not a sensitive value.
type SafeUint = i.SafeUint

// SafeFloat represents a floating-point value that is not a sensitive value.
type SafeFloat = i.SafeFloat

// SafeRune aliases rune. See the explanation for SafeString.
type SafeRune = i.SafeRune

Expand Down
18 changes: 18 additions & 0 deletions builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,24 @@ func (b *StringBuilder) SafeString(s i.SafeString) {
_, _ = b.Buffer.WriteString(string(s))
}

// SafeInt is part of the SafeWriter interface.
func (b *StringBuilder) SafeInt(s i.SafeInt) {
b.SetMode(ib.SafeEscaped)
_, _ = ifmt.Fprintf(&b.Buffer, "%d", s)
}

// SafeUint is part of the SafeWriter interface.
func (b *StringBuilder) SafeUint(s i.SafeUint) {
b.SetMode(ib.SafeEscaped)
_, _ = ifmt.Fprintf(&b.Buffer, "%d", s)
}

// SafeFloat is part of the SafeWriter interface.
func (b *StringBuilder) SafeFloat(s i.SafeFloat) {
b.SetMode(ib.SafeEscaped)
_, _ = ifmt.Fprintf(&b.Buffer, "%v", s)
}

// SafeRune is part of the SafeWriter interface.
func (b *StringBuilder) SafeRune(s i.SafeRune) {
b.SetMode(ib.SafeEscaped)
Expand Down
8 changes: 6 additions & 2 deletions builder/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ func TestBuilder(t *testing.T) {

b.SafeString("safe\n")

b.SafeInt(123)
b.SafeUint(456)
b.SafeFloat(3.14)

b.SafeRune('S')
b.SafeRune('\n')

Expand Down Expand Up @@ -70,7 +74,7 @@ safe
safe
hello safe ‹unsafe›
safe
S
1234563.14S
‹unsafe›
‹unsafe` + "\342" + `?›
‹U›
Expand All @@ -96,7 +100,7 @@ safe
safe
hello safe unsafe
safe
S
1234563.14S
unsafe
unsafe` + "\342" + `?
U
Expand Down
33 changes: 28 additions & 5 deletions interfaces/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ type SafeWriter interface {
// SafeString emits a safe string.
SafeString(SafeString)

// SafeInt emits a safe integer.
SafeInt(SafeInt)

// SafeUint emits a safe unsigned integer.
SafeUint(SafeUint)

// SafeFloat emits a safe floating-point value.
SafeFloat(SafeFloat)

// SafeRune emits a safe rune.
SafeRune(SafeRune)

Expand Down Expand Up @@ -80,16 +89,30 @@ type SafeWriter interface {
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.
// SafeString represents a string that is not a sensitive value.
type SafeString string

// SafeValue makes SafeString a SafeValue.
func (SafeString) SafeValue() {}

// SafeInt represents an integer that is not a sensitive value.
type SafeInt int64

// SafeValue makes SafeInt a SafeValue.
func (SafeInt) SafeValue() {}

// SafeUint represents an integer that is not a sensitive value.
type SafeUint uint64

// SafeValue makes SafeUint a SafeValue.
func (SafeUint) SafeValue() {}

// SafeFloat represents a floating-point value that is not a sensitive value.
type SafeFloat float64

// SafeValue makes SafeFloat a SafeValue.
func (SafeFloat) SafeValue() {}

// SafeRune aliases rune. See the explanation for SafeString.
type SafeRune rune

Expand Down
18 changes: 18 additions & 0 deletions internal/rfmt/printer_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ func (p *pp) SafeString(s i.SafeString) {
p.buf.WriteString(string(s))
}

// SafeInt implements SafePrinter.
func (p *pp) SafeInt(s i.SafeInt) {
defer p.startSafeOverride().restore()
p.fmtInteger(uint64(s), signed, 'd')
}

// SafeUint implements SafePrinter.
func (p *pp) SafeUint(s i.SafeUint) {
defer p.startSafeOverride().restore()
p.fmtInteger(uint64(s), unsigned, 'd')
}

// SafeFloat implements SafePrinter.
func (p *pp) SafeFloat(s i.SafeFloat) {
defer p.startSafeOverride().restore()
p.fmtFloat(float64(s), 64, 'v')
}

// SafeRune implements SafePrinter.
func (p *pp) SafeRune(r i.SafeRune) {
defer p.startSafeOverride().restore()
Expand Down
11 changes: 11 additions & 0 deletions markers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ func TestPrinter(t *testing.T) {
}{
{func(w p) { w.SafeString("ab") }, `ab`},
{func(w p) { w.SafeRune('☃') }, `☃`},
{func(w p) { w.SafeInt(-123) }, `-123`},
{func(w p) { w.SafeUint(123) }, `123`},
{func(w p) { w.SafeFloat(3.14) }, `3.14`},
{func(w p) { w.UnsafeString("rs") }, `‹rs›`},
{func(w p) { w.UnsafeByte('t') }, `‹t›`},
{func(w p) { w.UnsafeByte(m.StartS[0]) }, `‹?›`},
Expand All @@ -62,6 +65,11 @@ func TestPrinter(t *testing.T) {
{func(w p) { w.Print("ar", []byte{55, 56}) }, `‹ar›[‹55› ‹56›]`},
{func(w p) { w.Print("ar", Safe([]byte{55, 56})) }, `‹ar›[55 56]`},

// Numeric values.
{func(w p) { w.Printf("vn %+d", SafeInt(123)) }, `vn +123`},
{func(w p) { w.Printf("vn %05d", SafeUint(123)) }, `vn 00123`},
{func(w p) { w.Printf("vn %e", SafeFloat(3.14)) }, `vn 3.140000e+00`},

// Pre-redactable strings.
{func(w p) { w.Print("pr", RedactableString("hi")) }, `‹pr›hi`},
{func(w p) { w.Print("pr", RedactableBytes("hi")) }, `‹pr›hi`},
Expand Down Expand Up @@ -125,6 +133,9 @@ func TestPrinter(t *testing.T) {
{func(w p) { w.Print(Unsafe(RedactableString("ab‹c›"))) }, "‹ab?c?›"},
{func(w p) { w.Print(Unsafe(RedactableBytes("ab‹c›"))) }, "‹ab?c?›"},
{func(w p) { w.Print(Unsafe(SafeRune('a'))) }, "‹97›"},
{func(w p) { w.Print(Unsafe(SafeInt(-123))) }, "‹-123›"},
{func(w p) { w.Print(Unsafe(SafeUint(123))) }, "‹123›"},
{func(w p) { w.Print(Unsafe(SafeFloat(3.14))) }, "‹3.14›"},
{func(w p) { w.Print(Unsafe(Sprint("abc"))) }, "‹?abc?›"},
{func(w p) { w.Print(Unsafe(Safe("abc"))) }, "‹abc›"},
{func(w p) { w.Printf("%v", Unsafe(SafeString("abc"))) }, "‹abc›"},
Expand Down

0 comments on commit 2c44c49

Please sign in to comment.