Skip to content

pgproto3: hex-decode CopyData.Data in UnmarshalJSON#2569

Merged
jackc merged 1 commit into
jackc:masterfrom
c-tonneslan:fix/copydata-json-roundtrip
May 30, 2026
Merged

pgproto3: hex-decode CopyData.Data in UnmarshalJSON#2569
jackc merged 1 commit into
jackc:masterfrom
c-tonneslan:fix/copydata-json-roundtrip

Conversation

@c-tonneslan

Copy link
Copy Markdown
Contributor

Spotted while reading pgproto3/copy_data.go. CopyData.MarshalJSON uses hex.EncodeToString on Data but UnmarshalJSON does

dst.Data = []byte(msg.Data)

so any Data with non-printable bytes round-trips as the literal hex string back into the slice. e.g.

orig := CopyData{Data: []byte{0x01, 0x02, 0xff}}
b, _ := json.Marshal(orig)
// b = {"Type":"CopyData","Data":"0102ff"}
var got CopyData
json.Unmarshal(b, &got)
// got.Data == []byte{0x30, 0x31, 0x30, 0x32, 0x66, 0x66}

Now hex.DecodeString matches the marshal side. Kept the empty-Data shortcut so the existing TestJSONUnmarshalCopyData fixture ({"Type":"CopyData"} -> []byte{}) still passes. Added a round-trip test that fails on master.

MarshalJSON encodes Data with hex.EncodeToString but UnmarshalJSON did
[]byte(msg.Data), so round-tripping any CopyData with non-text bytes
through JSON would silently corrupt the payload (e.g. [0x01 0x02 0xff]
came back as the literal bytes for the string "0102ff"). Now mirrors
the marshal side with hex.DecodeString, with the empty-Data shortcut
preserved so the existing TestJSONUnmarshalCopyData fixture still
unmarshals to []byte{}.

Added a round-trip test.

Signed-off-by: Charlie Tonneslan <cst0520@gmail.com>
@jackc jackc merged commit 2464db9 into jackc:master May 30, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants