{
 "number": 35903,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35903",
 "title": "contrib: fix crash in message-capture-parser.py on non-printable msgtype",
 "author": "CapThunder19",
 "author_association": "FIRST_TIME_CONTRIBUTOR",
 "created_at": "2026-08-05T18:22:18Z",
 "updated_at": "2026-09-17T07:38:34Z",
 "age_days": 42,
 "draft": false,
 "labels": [
  "Scripts and tools"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "241385f21cfb5904fb7002f5be12c64fba55096d",
 "head_ref": "fix-message-capture-parser-crash",
 "head_repo": "CapThunder19/bitcoin",
 "head_history": [],
 "additions": 2,
 "deletions": 4,
 "changed_files": 1,
 "commit_count": 1,
 "size_bucket": "S",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {},
   "conflicts": []
  }
 },
 "acks_parsed": {},
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 0,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "sedited"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-08-05T18:17:56Z",
  "last_reviewer_activity": "2026-09-17T07:38:34Z",
  "last_reviewer": "sedited",
  "author_silent_days": 42,
  "waiting_on_author_days": 0,
  "days_since_update": 0
 },
 "refs": {
  "mentioned": [
   35883,
   35958
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 35883,
    "type": "issue",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "contrib: message-capture-parser.py crashes instead of labeling non-printable message types \\\"UNREADABLE\\\""
   },
   {
    "number": 35958,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-09-03",
    "title": "net: align v2 message type validation with v1 range"
   }
  ],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [],
 "body": "The unrecognized-message-type branch tries to fall back to \"UNREADABLE\"\nby doing `raise UnicodeDecodeError` with no arguments. That doesn't work\nUnicodeDecodeError needs 5 constructor arguments, so this actually raises\na TypeError, which the surrounding `except UnicodeDecodeError` doesn't\ncatch. The script crashes instead of labeling the message and continuing.\n\nSince output is only written after the whole capture file is processed,\none bad message type loses the entire parse.\n\nThis isn't just theoretical: v2 transport accepts message-type byte 0x7F\n(net.cpp, V2Transport::GetMessageType), which v1 rejects\n(protocol.cpp, IsMessageTypeValid). 0x7F is valid UTF-8 but not printable,\nso a peer sending an unrecognized v2 message type containing it produces\na capture record that crashes the parser on the next parse.\n\nRepro:\n\n    $ python3 -c \"\n    import struct\n    msgtype = b'\\x01bad' + b'\\x00'*8\n    open('msgs_recv.dat','wb').write(struct.pack('<q', 1234567890) + msgtype + struct.pack('<i', 0))\"\n    $ python3 contrib/message-capture/message-capture-parser.py msgs_recv.dat\n    TypeError: function takes exactly 5 arguments (0 given)\n\nWith this fix it correctly outputs `\"msgtype\": \"UNREADABLE\"` and exits 0.\n\nNote there's no automated test covering message-capture-parser.py's output\n(p2p_message_capture.py has its own separate structural parser and says\nthis script \"should be verified manually\")  likely why this went\nunnoticed. Verified manually with the repro above and confirmed the\nexisting invalid-UTF-8 fallback path is unaffected.\n\n#35883",
 "commits": [
  {
   "sha": "241385f21cfb5904fb7002f5be12c64fba55096d",
   "date": "2026-08-05T18:17:56Z",
   "message": "contrib: fix crash in message-capture-parser.py on non-printable msgtype"
  }
 ],
 "timeline": [
  {
   "t": "2026-09-17T07:38:34Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n(net.cpp, V2Transport::GetMessageType), which v1 rejects\n(protocol.cpp, IsMessageTypeValid). 0x7F is valid UTF-8 but not printable,\nso a peer sending an unrecognized v2 message type containing it produces\na capture record that crashes the parser on the next parse.\n\nIs this still relevant after #35958?"
  }
 ],
 "labels_log": [
  {
   "t": "2026-08-05T18:22:21Z",
   "action": "labeled",
   "label": "Scripts and tools",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 2029,
 "text_tokens_estimate": 507,
 "changed_paths": [
  "contrib/message-capture/message-capture-parser.py"
 ],
 "files": [
  {
   "path": "contrib/message-capture/message-capture-parser.py",
   "add": 2,
   "del": 4
  }
 ],
 "test_lines": 6,
 "git": {
  "head": "241385f21cfb5904fb7002f5be12c64fba55096d",
  "head_matches_backup": true,
  "base": "556988790a7f961693a8fd93f73725baea66476a",
  "commits": [
   {
    "sha": "241385f21c",
    "subject": "contrib: fix crash in message-capture-parser.py on non-printable msgtype",
    "files": 1,
    "add": 2,
    "del": 4
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "0eb760ed0c33265d",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}