{
 "number": 36366,
 "input_hash": "13aca77bf9eee554",
 "model": "ledger",
 "prompt_hash": null,
 "created": "2026-10-04T01:17:21+00:00",
 "result": {
  "summary": "Caps relative ban durations to UINT32_MAX in both the setban RPC and the -bantime configuration argument. The setban RPC rejects relative ban durations exceeding UINT32_MAX with an invalid parameter error, while -bantime clamps values greater than UINT32_MAX using std::min. Absolute timestamps remain unaffected.",
  "problem": "BanMan calculates ban expiration as GetTime() + bantime using signed 64-bit integers. If a relative ban duration near INT64_MAX is provided, the addition overflows, causing a signed integer overflow runtime error under UBSan; without UBSan, it wraps negative, causing the node to treat the ban as already expired and silently drop it while setban still returns success.",
  "card": "Caps relative ban durations to UINT32_MAX across the setban RPC and the -bantime startup option. Relative ban durations near INT64_MAX currently cause signed 64-bit integer overflow in BanMan, triggering UBSan errors and wrapping to negative timestamps that silently discard bans while reporting success. With this change, setban rejects relative durations exceeding UINT32_MAX, and -bantime clamps larger values without failing startup.",
  "evidence": [
   "PR description quotes a UBSan runtime error: src/banman.cpp:140:73: runtime error: signed integer overflow: 1790412558 + 9223372036854775807 cannot be represented in type 'int64_t'"
  ],
  "scope_notes": "",
  "changed_since_previous": "Switched from parsing -bantime as uint32_t to keeping GetIntArg and clamping with std::min so oversized values in settings.json do not abort node startup, and added a test for settings.json.",
  "thread": {
   "last_event_at": "2026-10-02T15:01:36Z",
   "events": 7,
   "head_sha": "514ff32e2f2024555bb9f157a6e16e311af9fd9f",
   "schema_floor": 2,
   "schema": 2
  },
  "waiting_on": [
   {
    "at": "2026-10-02",
    "id": "rc:4166957853",
    "on": "reviewer",
    "url": "https://github.com/bitcoin/bitcoin/pull/36366#discussion_r4166957853",
    "what": "willcl-ark to review fix for settings.json bantime parsing"
   }
  ],
  "risk": {
   "level": "medium",
   "touches": [
    "rpc_api"
   ],
   "why": "A flaw in duration validation could reject valid bans or cause bans to expire at unintended times for node operators."
  },
  "discussion": {
   "author_status": "last statement processed 2026-10-02",
   "open_concerns": [],
   "resolved_concerns": [
    "maflcko: Supporting durations unsupported by C++ chrono using SaturatingAdd does not work for chrono types; excessively large bantime arguments should be rejected instead (accepted by maflcko 2026-09-29)",
    "maflcko: Reject relative ban times above UINT32_MAX to avoid a time dependency (accepted by maflcko 2026-09-29)",
    "maflcko: Parse bantime as u32 (accepted by maflcko 2026-09-29)",
    "willcl-ark: A bantime value greater than uint32 in settings.json throws during conversion on startup (fixed by Bruce039 2026-10-02)"
   ]
  },
  "reviewability": {
   "state": "Ready",
   "label": "Ready",
   "reason": "Nothing known that would invalidate a review now."
  },
  "agreement": {
   "state": "Strong",
   "summary": "Strong: substantive support, no open objection (maflcko)",
   "reason": "willcl-ark pointed out an issue where values > uint32 in settings.json throw on startup; the author pushed a fix parsing as int64 and capping at UINT32_MAX.",
   "evidence": [
    "maflcko: ACK \u2014 Seems fine to reject or clamp values larger than any meaningful use-case."
   ],
   "objections": [
    {
     "reviewer": "maflcko",
     "association": "MEMBER",
     "type": "objection",
     "kind": "approach",
     "harm": "Supporting durations unsupported by C++ chrono using SaturatingAdd does not work for chrono types; excessively large bantime arguments should be rejected instead",
     "request": "",
     "question": "",
     "text": "Supporting durations unsupported by C++ chrono using SaturatingAdd does not work for chrono types; excessively large bantime arguments should be rejected instead",
     "clears_with": "change",
     "blocking": true,
     "status": "accepted",
     "status_note": "author switched to rejecting large bantimes and reviewer accepted with an ACK",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "c:5874821692"
     ],
     "evidence": "2026-09-28: 'I am not sure about starting/trying to support durations that C++ itself doesn't even support... Also, `SaturatingAdd` doesn't work for chrono types ...'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36366#issuecomment-5872774469",
     "id": "c:5872774469",
     "at": "2026-09-28",
     "status_at": "2026-09-29",
     "status_by": "maflcko",
     "resolution_evidence": "2026-09-29: maflcko: 'Seems fine to reject or clamp values larger than any meaningful use-case.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "maflcko",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "approach",
     "harm": "",
     "request": "Reject relative ban times above UINT32_MAX to avoid a time dependency",
     "question": "",
     "text": "Reject relative ban times above UINT32_MAX to avoid a time dependency",
     "clears_with": "answer",
     "blocking": false,
     "status": "accepted",
     "status_note": "author implemented uint32 limit in setban and reviewer ACKed",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4130783968"
     ],
     "evidence": "2026-09-29: 'This should be more than enough and also avoid the weird time dependency.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36366#discussion_r4130336905",
     "id": "rc:4130336905",
     "at": "2026-09-29",
     "status_at": "2026-09-29",
     "status_by": "maflcko",
     "resolution_evidence": "2026-09-29: maflcko: 'lgtm ACK d49c1c9ab3e139158d76141b71943ff79903e87a'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "maflcko",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "approach",
     "harm": "",
     "request": "Parse bantime as u32",
     "question": "",
     "text": "Parse bantime as u32",
     "clears_with": "answer",
     "blocking": false,
     "status": "accepted",
     "status_note": "author parsed -bantime as uint32_t and reviewer ACKed",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4130783968"
     ],
     "evidence": "2026-09-29: 'What about parsing it as u32?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36366#discussion_r4130336905",
     "id": "rc:4130336905#2",
     "at": "2026-09-29",
     "status_at": "2026-09-29",
     "status_by": "maflcko",
     "resolution_evidence": "2026-09-29: maflcko: 'lgtm ACK d49c1c9ab3e139158d76141b71943ff79903e87a'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "willcl-ark",
     "association": "MEMBER",
     "type": "objection",
     "kind": "correctness",
     "harm": "A bantime value greater than uint32 in settings.json throws during conversion on startup",
     "request": "",
     "question": "",
     "text": "A bantime value greater than uint32 in settings.json throws during conversion on startup",
     "clears_with": "change",
     "blocking": true,
     "status": "fixed",
     "status_note": "author reverted -bantime parsing to int64, capped at UINT32_MAX, and added a test case",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4166957853"
     ],
     "evidence": "2026-10-02: 'settings.json can also have a value > uint32 which will throw during conversion'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36366#discussion_r4164461680",
     "id": "rc:4164461680",
     "at": "2026-10-02",
     "status_at": "2026-10-02",
     "status_by": "Bruce039",
     "resolution_evidence": "2026-10-02: Bruce039: '`-bantime` is now read as int64 again and capped at UINT32_MAX, so it no longer matters where the value comes from.'",
     "pin": null,
     "from_schema": 2
    }
   ],
   "support": [
    {
     "reviewer": "maflcko",
     "reason": "Seems fine to reject or clamp values larger than any meaningful use-case.",
     "substantive": true,
     "verdict": "ACK",
     "id": "c:5886145451",
     "url": "https://github.com/bitcoin/bitcoin/pull/36366#issuecomment-5886145451",
     "at": "2026-09-29",
     "association": "MEMBER",
     "evidence": "read",
     "areas": []
    }
   ],
   "participants": [
    {
     "login": "maflcko",
     "stance": "support",
     "note": "ACKed after author addressed objection to SaturatingAdd and adopted suggestions to limit bantime to uint32",
     "association": "MEMBER",
     "comments": 3,
     "first": "2026-09-28",
     "last": "2026-09-29"
    },
    {
     "login": "willcl-ark",
     "stance": "objection",
     "note": "pointed out bantime > uint32 in settings.json throws on startup",
     "association": "MEMBER",
     "comments": 1,
     "first": "2026-10-02",
     "last": "2026-10-02"
    }
   ],
   "derivation": "substantive support, no open objection (maflcko)",
   "model_state": null,
   "corrections": [],
   "notes": "willcl-ark pointed out an issue where values > uint32 in settings.json throw on startup; the author pushed a fix parsing as int64 and capping at UINT32_MAX."
  },
  "dependencies": {
   "depends_on": [],
   "enables": []
  },
  "categories": [
   {
    "name": "rpc",
    "member": true,
    "evidence": "Matches RPC/REST/ZMQ label and modifies `src/rpc/net.cpp` parameter validation for the `setban` RPC method.",
    "band": "P3",
    "reason_tag": "bug fix",
    "score": 0.35,
    "factors": {
     "bug_severity": 1,
     "leverage": 0,
     "performance": 0,
     "security_stability": 1,
     "user_value": 0
    },
    "rationale": "Prevents signed integer overflow and silent ban drops when callers provide relative ban times near INT64_MAX. As noted in the description, 'GetTime() + bantime... wraps negative, causing the node to treat the ban as already expired and silently drop it while setban still returns success.'"
   },
   {
    "name": "utils",
    "member": false,
    "evidence": "The one-line edit in `src/init.cpp` clamping `-bantime` is a settings adjustment whose purpose is peer banning behavior; utils explicitly excludes settings changes whose point is another area's behavior.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 1,
     "leverage": 0,
     "performance": 0,
     "security_stability": 1,
     "user_value": 0
    },
    "rationale": "Not a utils change; the single-line clamp to `-bantime` in init.cpp serves peer-banning logic rather than shared infrastructure."
   }
  ],
  "confidence": "high",
  "uncertainties": [],
  "needs": []
 },
 "cost_usd": 0.0,
 "source": {
  "record": "2026-10-04T01:17:21+00:00",
  "code": "2026-10-04T01:20:31+00:00",
  "judgments": 2
 }
}