)]}'
{
  "commit": "05d1592af5bf6cc7978c2f8c0d20ec2f6e8471d2",
  "tree": "34d1b1c99ecbb2cf665c5c7b3e97df1f00cff6f0",
  "parents": [
    "8e95bd49dd21866c3497658152f71cad41ce10b8"
  ],
  "author": {
    "name": "Showta Ishizaki",
    "email": "zakinko@snowrabbit.org",
    "time": "Mon Oct 26 08:37:09 2026 -0700"
  },
  "committer": {
    "name": "Copybara-Service",
    "email": "copybara-worker@google.com",
    "time": "Mon Oct 26 08:38:18 2026 -0700"
  },
  "message": "Do not replace /dev/null with a regular file in WriteFile (#31038)\n\nWriteFile unlinks its target before creating it with O_CREAT. The unlink is\nthere so a running executable can be replaced, since you cannot open one with\nO_TRUNC; it has been in the function since the first import, when WriteFile\u0027s\njob was to write executables: the open used mode 0755 and the comment said so.\n\n`//src/test/cpp/util:file_test` writes to /dev/null, in TestWriteFile and again\nwith a four-gigabyte NUL-filled buffer in TestLargeFileWrite. As an ordinary\nuser the unlink fails and the write reaches the device, so nothing happens.\nAs root it succeeds and the node becomes a regular file.\n\nOn GitHub\u0027s ubuntu-latest runner, where /dev is devtmpfs, at 870abbbd,\nrunning the test as root:\n\n    before   /dev/null  character special file  crw-rw-rw-  1:3\n    //src/test/cpp/util:file_test    PASSED\n    after    /dev/null  regular file            -rw-r--r--  0:0  size\u003d215\n\nDebian 13 in a container and NetBSD 11.0/amd64 do the same. On NetBSD,\npolling once a second while TestLargeFileWrite runs:\n\n    t\u003d7  Character Device  size\u003d0\n    t\u003d8  Regular File      size\u003d4000000000\n    t\u003d9  Regular File      size\u003d0\n\n/dev holds a four-gigabyte file for about a second, until the next thing that\nredirects to /dev/null truncates it.\n\nWhat follows the missing device is harder to find than the device itself:\n`2\u003e/dev/null` becomes a write, and the next program to read /dev/null gets\nwhatever was left there.\n\nfile_windows.cc already returns early for /dev/null. This is the same three\nlines on the POSIX side. The POSIX test then writes to /dev/null and checks\nthat it is still a device: as an ordinary user that cannot fail, and as root\nit fails there instead of quietly corrupting everything that runs after it.\n\n    without the change, as root   file_posix_test.cc:336  Expected: true   FAILED\n    with the change, as root      PASSED, /dev/null still 1:3\n\nfile_test passes as an ordinary user on ubuntu-latest, macos-latest and\nwindows-latest (the Windows build does not compile either file touched here).\nThe tests that fail as root do so before and after alike:\nFilePosixTest.CanAccess and FileTest.TestRemoveRecursivelyPosix.\n\nCloses #31038\n\nCOPYBARA_INTEGRATE_REVIEW\u003dhttps://github.com/bazelbuild/bazel/pull/31038 from zakinko:devnull-unlink 387d25a62bacb37fe62dd69b59d2af2aac450fb5\nPiperOrigin-RevId: 1007302902\nChange-Id: I8330d24a86a55799473113849ff10b0f327d928f\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "b51f6525f21a50f9d8374f8b2f16e53c091a8839",
      "old_mode": 33188,
      "old_path": "src/main/cpp/util/file_posix.cc",
      "new_id": "3b1bf69d87158f4e5b760021ed18c323d710c40d",
      "new_mode": 33188,
      "new_path": "src/main/cpp/util/file_posix.cc"
    },
    {
      "type": "modify",
      "old_id": "80a6fac288bf7aa19d6443707b7e5b4a4f79ab05",
      "old_mode": 33188,
      "old_path": "src/test/cpp/util/file_posix_test.cc",
      "new_id": "1c15ab40f1fdf54944c0b4252fb0f47139dd676e",
      "new_mode": 33188,
      "new_path": "src/test/cpp/util/file_posix_test.cc"
    }
  ]
}
