wire: add test for trailing bytes rejection in ReadMessage
What changed, and why it matters
This commit only adds a new unit test. It does not change any production code. The test checks that ReadMessage correctly rejects Bitcoin wire messages that have extra garbage bytes appended after the expected payload. The test is verifying behavior that was apparently added in a prior commit (the message mentions a 'new trailing-bytes check'). On its own, this commit is not a security fix and does not introduce a vulnerability.
No action required. This is a test-only commit. If reviewing the related trailing-bytes check, ensure it is present and correct in the production implementation of readMessageWithEncodingNInternal / ReadMessageN.
Security signals we found
Test-only change
Defensive parsing behavior is being verified, not introduced
No production code paths are modified
Evidence from the diff
The diff adds TestReadMessageTrailingBytes to wire/message_test.go. The test builds a valid version message payload, appends 4 bytes (0xdeadbeef), constructs a correct wire header whose checksum covers the dirty payload, and then calls ReadMessageN. It asserts that the function returns a *MessageError because of unconsumed trailing bytes. No production code is modified. The commit message references a ‘new trailing-bytes check in readMessageWithEncodingNInternal’, implying the defensive check exists elsewhere and this test merely covers it.
Changed components
wire/message_test.goInspect captured patch +50 / −0
diff --git a/wire/message_test.go b/wire/message_test.go
index a9c8389..8b40250 100644
--- a/wire/message_test.go
+++ b/wire/message_test.go
@@ -7,6 +7,7 @@ package wire
import (
"bytes"
"encoding/binary"
+ "errors"
"io"
"net"
"reflect"
@@ -346,6 +347,7 @@ func TestReadMessageWireErrors(t *testing.T) {
ErrUnknownMessage,
24,
},
+
}
t.Logf("Running %d tests", len(tests))
@@ -378,6 +380,54 @@ func TestReadMessageWireErrors(t *testing.T) {
}
}
+// TestReadMessageTrailingBytes verifies that a message with unconsumed
+// trailing bytes after BtcDecode is rejected with a MessageError.
+func TestReadMessageTrailingBytes(t *testing.T) {
+ t.Parallel()
+
+ pver := ProtocolVersion
+ btcnet := MainNet
+
+ me := &NetAddress{
+ Timestamp: time.Time{},
+ IP: net.ParseIP("127.0.0.1"),
+ Port: 8333,
+ }
+ you := &NetAddress{
+ Timestamp: time.Time{},
+ IP: net.ParseIP("192.168.0.1"),
+ Port: 8333,
+ }
+ verMsg := NewMsgVersion(me, you, 1, 0)
+
+ // Serialize the version message payload only (no wire header).
+ var payloadBuf bytes.Buffer
+ verMsg.BtcEncode(&payloadBuf, pver, BaseEncoding)
+ cleanPayload := payloadBuf.Bytes()
+
+ // Append garbage bytes to the valid payload.
+ garbage := []byte{0xde, 0xad, 0xbe, 0xef}
+ dirtyPayload := append(cleanPayload, garbage...)
+
+ // Build the wire frame: header + dirty payload with correct
+ // checksum over the full (dirty) payload.
+ checksum := chainhash.DoubleHashB(dirtyPayload)
+ hdr := makeHeader(btcnet, CmdVersion, uint32(len(dirtyPayload)), 0)
+ copy(hdr[20:], checksum[:4])
+ wireBytes := append(hdr, dirtyPayload...)
+
+ r := bytes.NewReader(wireBytes)
+ _, _, _, err := ReadMessageN(r, pver, btcnet)
+ if err == nil {
+ t.Fatal("expected error for message with trailing bytes")
+ }
+
+ var msgErr *MessageError
+ if !errors.As(err, &msgErr) {
+ t.Fatalf("expected MessageError, got: %T (%v)", err, err)
+ }
+}
+
// TestWriteMessageWireErrors performs negative tests against wire encoding from
// concrete messages to confirm error paths work correctly.
func TestWriteMessageWireErrors(t *testing.T) {
Why this scored 12/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.