)]}'
{
  "commit": "7029f99cc62beb9f8c2b13dfaaa1ef04e040cb60",
  "tree": "92626e4bc90e441f1ca1203761da233ee721e1e7",
  "parents": [
    "288913638bb2da563f1c39e7d07071c2f21bfb25"
  ],
  "author": {
    "name": "Agis Kounelis",
    "email": "36283973+kounelisagis@users.noreply.github.com",
    "time": "Thu Apr 16 07:08:06 2026 +0300"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Wed Apr 15 21:08:06 2026 -0700"
  },
  "message": "fix: segfault when moving `scoped_ostream_redirect` (#6033)\n\n* fix: segfault when moving `scoped_ostream_redirect`\n\nThe default move constructor left the stream (`std::cout`) pointing at\nthe moved-from `pythonbuf`, whose internal buffer and streambuf pointers\nwere nulled by the move. Any subsequent write through the stream\ndereferenced null, causing a segfault.\n\nReplace `\u003d default` with an explicit move constructor that re-points\nthe stream to the new buffer and disarms the moved-from destructor.\n\n* fix: mark move constructor noexcept to satisfy clang-tidy\n\n* fix: use bool flag instead of nullptr sentinel for moved-from state\n\nUsing `old \u003d\u003d nullptr` as the moved-from sentinel was incorrect because\nnullptr is a valid original rdbuf() value (e.g. `std::ostream os(nullptr)`).\nReplace with an explicit `active` flag so the destructor correctly\nrestores nullptr buffers.\n\nAdd tests for the nullptr-rdbuf edge case.\n\n* fix: remove noexcept and propagate active flag from source\n\n- Remove noexcept: pythonbuf inherits from std::streambuf whose move\n  is not guaranteed nothrow on all implementations. Suppress clang-tidy\n  with NOLINTNEXTLINE instead.\n- Initialize active from other.active so that moving an already\n  moved-from object does not incorrectly re-activate the redirect.\n- Only rebind the stream and disarm the source when active.\n\n* test: add unflushed ostream redirect regression\n\nCover the buffered-before-move case for `scoped_ostream_redirect`, which still crashes despite the current move fix. This gives the PR a direct reproducer for the remaining bug path.\n\nMade-with: Cursor\n\n* fix: disarm moved-from pythonbuf after redirect move\n\nThe redirect guard now survives moves, but buffered output could still remain in the moved-from `pythonbuf` and be flushed during destruction through moved-out Python handles. Rebuild the destination put area from the transferred storage and clear the source put area so unflushed bytes follow the active redirect instead of crashing in the moved-from destructor.\n\nMade-with: Cursor\n\n---------\n\nCo-authored-by: Ralf W. Grosse-Kunstleve \u003crgrossekunst@nvidia.com\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "44261e881e13a9520088418fe32d099596717ad1",
      "old_mode": 33188,
      "old_path": "include/pybind11/iostream.h",
      "new_id": "df7fa3c3819f08f2e4d13b6f4f3c11d98d748f3e",
      "new_mode": 33188,
      "new_path": "include/pybind11/iostream.h"
    },
    {
      "type": "modify",
      "old_id": "421eaa2dd896af80be1834281fe1a5fd668e10c9",
      "old_mode": 33188,
      "old_path": "tests/test_iostream.cpp",
      "new_id": "7484e734be670c5e5e1dab589dcded66159771df",
      "new_mode": 33188,
      "new_path": "tests/test_iostream.cpp"
    },
    {
      "type": "modify",
      "old_id": "791b9e04831825a2dac819ddd10f96e6b2dccda1",
      "old_mode": 33188,
      "old_path": "tests/test_iostream.py",
      "new_id": "857e0b5f732eb0f77e90773f5668006b5d2908fd",
      "new_mode": 33188,
      "new_path": "tests/test_iostream.py"
    }
  ]
}
