Commit f3c85c50 authored by Rob Pike's avatar Rob Pike

fmt: fix bug in scanning of hex strings

Couldn't handle a hex string terminated by anything
other than spaces. Easy to fix.

Fixes #9124.

Change-Id: I18f89a0bd99a105c9110e1ede641873bf9daf3af
Reviewed-on: https://go-review.googlesource.com/1538Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 79a4a779
......@@ -1231,7 +1231,7 @@ func TestNilDoesNotBecomeTyped(t *testing.T) {
type B struct{}
var a *A = nil
var b B = B{}
got := Sprintf("%s %s %s %s %s", nil, a, nil, b, nil)
got := Sprintf("%s %s %s %s %s", nil, a, nil, b, nil) // go vet should complain about this line.
const expect = "%!s(<nil>) %!s(*fmt_test.A=<nil>) %!s(<nil>) {} %!s(<nil>)"
if got != expect {
t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got)
......
......@@ -875,34 +875,40 @@ func (s *ss) quotedString() string {
return ""
}
// hexDigit returns the value of the hexadecimal digit
func (s *ss) hexDigit(d rune) int {
// hexDigit returns the value of the hexadecimal digit.
func hexDigit(d rune) (int, bool) {
digit := int(d)
switch digit {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return digit - '0'
return digit - '0', true
case 'a', 'b', 'c', 'd', 'e', 'f':
return 10 + digit - 'a'
return 10 + digit - 'a', true
case 'A', 'B', 'C', 'D', 'E', 'F':
return 10 + digit - 'A'
return 10 + digit - 'A', true
}
s.errorString("illegal hex digit")
return 0
return -1, false
}
// hexByte returns the next hex-encoded (two-character) byte from the input.
// There must be either two hexadecimal digits or a space character in the input.
// It returns ok==false if the next bytes in the input do not encode a hex byte.
// If the first byte is hex and the second is not, processing stops.
func (s *ss) hexByte() (b byte, ok bool) {
rune1 := s.getRune()
if rune1 == eof {
s.UnreadRune()
return
}
if isSpace(rune1) {
value1, ok := hexDigit(rune1)
if !ok {
s.UnreadRune()
return
}
rune2 := s.mustReadRune()
return byte(s.hexDigit(rune1)<<4 | s.hexDigit(rune2)), true
value2, ok := hexDigit(s.mustReadRune())
if !ok {
s.errorString("illegal hex digit")
return
}
return byte(value1<<4 | value2), true
}
// hexString returns the space-delimited hexpair-encoded string.
......
......@@ -864,7 +864,7 @@ func TestScanStateCount(t *testing.T) {
t.Fatal(err)
}
if n != 3 {
t.Fatalf("expected 3 items consumed, got %d")
t.Fatalf("expected 3 items consumed, got %d", n)
}
if a.rune != '1' || b.rune != '2' || c.rune != '➂' {
t.Errorf("bad scan rune: %q %q %q should be '1' '2' '➂'", a.rune, b.rune, c.rune)
......@@ -990,3 +990,57 @@ func BenchmarkScanRecursiveInt(b *testing.B) {
b.StopTimer()
}
}
// Issue 9124.
// %x on bytes couldn't handle non-space bytes terminating the scan.
func TestHexBytes(t *testing.T) {
var a, b []byte
n, err := Sscanf("00010203", "%x", &a)
if n != 1 || err != nil {
t.Errorf("simple: got count, err = %d, %v; expected 1, nil", n, err)
}
check := func(msg string, x []byte) {
if len(x) != 4 {
t.Errorf("%s: bad length %d", msg, len(x))
}
for i, b := range x {
if int(b) != i {
t.Errorf("%s: bad x[%d] = %x", msg, i, x[i])
}
}
}
check("simple", a)
a = nil
n, err = Sscanf("00010203 00010203", "%x %x", &a, &b)
if n != 2 || err != nil {
t.Errorf("simple pair: got count, err = %d, %v; expected 2, nil", n, err)
}
check("simple pair a", a)
check("simple pair b", b)
a = nil
b = nil
n, err = Sscanf("00010203:", "%x", &a)
if n != 1 || err != nil {
t.Errorf("colon: got count, err = %d, %v; expected 1, nil", n, err)
}
check("colon", a)
a = nil
n, err = Sscanf("00010203:00010203", "%x:%x", &a, &b)
if n != 2 || err != nil {
t.Errorf("colon pair: got count, err = %d, %v; expected 2, nil", n, err)
}
check("colon pair a", a)
check("colon pair b", b)
a = nil
b = nil
// This one fails because there is a hex byte after the data,
// that is, an odd number of hex input bytes.
n, err = Sscanf("000102034:", "%x", &a)
if n != 0 || err == nil {
t.Errorf("odd count: got count, err = %d, %v; expected 0, error", n, err)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment