From f02cdba16398cee70a69262a55eb357dac6f81df Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Mon, 6 Feb 2023 14:48:19 -0800 Subject: [PATCH] encoding/hex: fix Decode output check regression CL 461958 fixed a potential panic, but also introduced an observable regression where invalid input could be detected before the panic occurs. Adjust the check to preserve prior behavior, while also preventing the panic. Change-Id: I52819f88a6a64883fbc9fd512697c38c29ca0ccd Reviewed-on: https://go-review.googlesource.com/c/go/+/465855 Auto-Submit: Joseph Tsai TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills Run-TryBot: Joseph Tsai Reviewed-by: Ian Lance Taylor --- src/encoding/hex/hex.go | 6 +++--- src/encoding/hex/hex_test.go | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/encoding/hex/hex.go b/src/encoding/hex/hex.go index 5a8243ae80..f69abb2f7f 100644 --- a/src/encoding/hex/hex.go +++ b/src/encoding/hex/hex.go @@ -75,9 +75,6 @@ func DecodedLen(x int) int { return x / 2 } // If the input is malformed, Decode returns the number // of bytes decoded before the error. func Decode(dst, src []byte) (int, error) { - if len(dst) < DecodedLen(len(src)) { - return 0, errors.New("encoding/hex: output buffer too small") - } i, j := 0, 1 for ; j < len(src); j += 2 { p := src[j-1] @@ -91,6 +88,9 @@ func Decode(dst, src []byte) (int, error) { if b > 0x0f { return i, InvalidByteError(q) } + if i >= len(dst) { + return i, errors.New("encoding/hex: output buffer too small") + } dst[i] = (a << 4) | b i++ } diff --git a/src/encoding/hex/hex_test.go b/src/encoding/hex/hex_test.go index 1eb169cdee..8d1ae70774 100644 --- a/src/encoding/hex/hex_test.go +++ b/src/encoding/hex/hex_test.go @@ -55,13 +55,16 @@ func TestDecode(t *testing.T) { } } -func TestDecode_tooFewDstBytes(t *testing.T) { +func TestDecodeDstTooSmall(t *testing.T) { dst := make([]byte, 1) src := []byte{'0', '1', '2', '3'} - _, err := Decode(dst, src) + n, err := Decode(dst, src) if err == nil { t.Errorf("expected Decode to return an error, but it returned none") } + if !bytes.Equal(dst[:n], []byte{0x01}) { + t.Errorf("output mismatch: got %x, want 01", dst[:n]) + } } func TestEncodeToString(t *testing.T) { -- 2.50.0